'unlabeled-1.4.770'.
+++ /dev/null
-.Xrefs
-aclocal.m4
-config.log
-config.status
-config.cache
-configure
-Makefile
-Makefile.in
-.deps
-tags
-TAGS
-lustre*.tar.gz
-cscope.files
-cscope.out
+++ /dev/null
-include /dev/obd in the documentation
-
-
-attach: attaching ext2obd allows ext2 module to be unloaded. Unload,
-then do cleanup, get Oops...
-
-syncing: invalid IOCTL
-
-create: more than one object
-
-preallocate: IOCTL
-
-statfs:
-
-restoresnap: decrements directory count for ext2
+++ /dev/null
-BUILDING LUSTRE
----------------
-
-To build the lustre obd module, you must first build portals.
-
-Portals is available from the same CVS repository of the lustre
-project module portals, see http://www.lustre.org
-
-To build:
- sh autogen.sh
- ./configure --enable-linuxdir=/usr/src/linux --enable-portalsdir=/usr/src/portals
- make
-
-To play with Lustre Lite:
- cd obd/tests
- sh llmount.sh
-
-To clean up:
- sh llmountcleanup.sh
-
-Feedback:
- lustre-devel@lists.sf.net
- lustre-discuss@lists.sf.net
-
-- Peter -
\ No newline at end of file
+++ /dev/null
-
- NOTE! This copyright does *not* cover user programs that use kernel
- services by normal system calls - this is merely considered normal use
- of the kernel, and does *not* fall under the heading of "derived work".
- Also note that the GPL below is copyrighted by the Free Software
- Foundation, but the instance of code that it refers to (the Linux
- kernel) is copyrighted by me and others who actually wrote it.
-
- Linus Torvalds
-
-----------------------------------------
-
- 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.
-\f
- 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.)
-\f
-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.
-\f
- 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.
-\f
- 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
-\f
- 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) 19yy <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) 19yy 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.
+++ /dev/null
-TBA
- * bug fixes
- - LRU counters were broken, causing constant lock purge (433, 432)
- - garbage on read from stripes with failed OSTs (441)
- - mark OSCs as active before reconnecting during recovery (438)
- - lov_enqueue and lov_cancel need to handle inactive OSTs (403)
-
-2002-12-02 Andreas Dilger <adilger@clusterfs.com>
- * version v0_5_18
- * bug fixes
- - fix many simultaneous client startup (392)
- - fix dentry->d_it clobbering
- - credentials weren't being shipped for readdir/getattr operations
- - remove invalid assertions triggered during some concurrent MD
- updates
- - proper Lustre versions added (336, 389)
- - fix memory leak for create error case (398)
- - fix LOV locking bug that would get cli/srv out of sync
- - fix echo client over LOV (409)
- - fix dbench 2, extN refcount problem (170, 258, 356, 418)
- - fix double-O_EXCL intent crash (424)
- - avoid sending multiple lock CANCELs (352)
- * Features
- - MDS can do multi-client recovery (modulo bugs in new code)
- * Documentation
- - many updates, edits, cleanups
-
-2002-11-18 Phil Schwan <phil@clusterfs.com>
- * version v0_5_17
- * bug fixes
- - fix null d_it dereference (346)
- - fix full OST/dbench hang (333)
- - fix permission problem with file removal (286)
- - fix removal of OSCs from LOV when they fail
- - fix NULL deref during bulk timeout (214)
- - fix problems related to multiple filesystems on one MDS (241)
- - fixed serious subtle metadata locking bugs
- - free locks on clients when inodes are removed due to memory
- pressure (201)
- - fix inode pointer in lock data (285)
- - partial support for multiple MDS on a single host (241)
- - data locks weren't cancelled at clear_inode time (290, 311)
- - intent locks could lead to unbounded lock growth (205)
- - added a maximum lock count, an LRU list, and a flusher
- - fix multiple rename (365)
- - properly abstracted the echo client
- - OSC locked 1 byte too many; fixed
- - rewrote brw callback code:
- - fixed recovery bugs related to LOVs (306)
- - fixed too-many-pages-in-one-write crash (191)
- - fixed (again) crash in sync_io_timeout (214)
- - probably fixed callback-related race (385)
- * protocol change
- - Add capability to MDS protocol
- - LDLM cancellations and callbacks on different portals
-
-2002-10-28 Andreas Dilger <adilger@clusterfs.com>
- * version v0_5_16
- * bug fixes:
- - limit client IOV size to PTL_MD_MAX_IOV (611336, 191)
- - defer open object destruction to close time (601981, 138)
- - open/close OST file handle in obdo (OBD_MD_FLHANDLE) (601981, 138)
- - move LDLM_ENQUEUE/CONVERT back to MDS portal (625069)
- - abstract ll_lookup2, fix ll_revalidate2 to use abstraction (256)
- - don't call obd_setattr in ll_file_release for destroyed objects
- * protocol change to lustre_msg: move |version| and add |flags|
- * protocol change to osc_punch: "start" in "o_size", "end" in "o_blocks"
- * lock replay: for LDLM_FL_REPLAY trust client to do right thing
- * added replay of create, unlink, link and rename operations during
- MDS failover; recovery should be much more robust now
- * remove failed OSCs from LOVs (only lov_create uses this so far)
- * the lustre-HOWTO was brought (more) up to date (582544)
-
-2002-10-23 Phil Schwan <phil@clusterfs.com>
- * version v0_5_15
- * bug fixes:
- - in-use dentries weren't being reused properly (617851)
- - prevent multiple LDLM setup (599178)
- - fix LOV size calculations for truncate (617853)
- - fix client handling of MDS intent errors (POSIX)
- - fix permission bug in lovstripe.c test (624321)
- - fix MDS thread deadlock - move LDLM handler to DLM portal (625069)
- - truncate past end of file could corrupt data
- - proper cleanup after timeouts, crashes, etc (592524, 550815)
- - a race in recovery could return ETIMEDOUT to apps (623947)
- - building outside the source directory was fixed
- * the lustre-HOWTO was brought (more) up to date (582544)
- * major progress was made on recovery functionality
-
-2002-10-10 Phil Schwan <phil@clusterfs.com>
- * version v0_5_14
- * bug fixes:
- - recovery deadlock fix
- - rm -rf causes LBUG fix (617817)
- - file open by multiple tasks fix (618962)
- - directory permissions bugs (602707 and 620007)
- - journal_stop fixed with locking (611313)
- - O_APPEND failures resolved (618273, perhaps 614459)
- - lconf PATH fix (619770)
- - IA64 build fix (621450)
- - RPC buffer sizes scale with amount of memory
-
-2002-10-01 Phil Schwan <phil@clusterfs.com>
- * version v0_5_13
- * bug fixes:
- - locks would be cancelled without throwing away data pages,
- resulting in inconsistent data (605627)
- - inode attributes were not always being refreshed (605627, 612449)
- - lconf now continues to cleanup after lctl reports an error
- - MDS now enforces user permissions (602707)
- - lprocfs cleanup fixed, but not yet enabled (614157)
- - fixed infinite server hang, should a client not respond to an AST
- - avoid going into recovery if user calls readlink() with a buffer
- that's too small (613941)
- - AST RPCs no longer require replies (614867) -- this may be changed
- - don't crash server if client sends an IOV that's too big (611336)
- - fixed lock conversion deadlock (611892)
- - fixed the following of symlinks (614622)
- * recovery: the server can remove locks from a client that dies, other
- clients can make progress
- * more extN patch fixes
- * compile-time configurable ptlrpc buffer allocations
- * documentation
- - collaborative read cache document
- - Lustre Lite Performance CDR document-in-progress
-
-2002-09-20 Andreas Dilger <adilger@clusterfs.com>
- * version v0_5_12
- * bug fix
- - fix typo in patch-2.4.18
-
-2002-09-20 Andreas Dilger <adilger@clusterfs.com>
- * version v0_5_11
- * bug fixes
- - clear ptlrpc request each time in handle_incoming_request()
- - unlink of files now destroys the object on the OST
-
-2002-09-19 Peter Braam <braam@clusterfs.com>
- * version 0_5_10
- * add hard link support
- * change obdfile creation method
- * kernel patch changed
-
-2002-09-19 Peter Braam <braam@clusterfs.com>
- * version 0_5_9
- * bug fix
- - stack overflow bug in extN fixed
-
-2002-09-18 Andreas Dilger <adilger@clusterfs.com>
- * version 0_5_8
- * documentation updates
- - add man pages for config tools
- - update tests/README to describe testing with new config tools
- - finish metadata API descriptions
- * bug fixes and cleanups
- - statfs workaround for 16TB limit
- - LOV stripe allocation improved, can stripe on subset of OSTs
- - LOV file size/IO offset was wrong for files > 4GB in size
- - object EA data was being dropped, caused files to be unreadable
- - memory overflow with non-LOV OST caused memory corruption
- - fixed regression tests to work with new config tools, obdfilter
- - fixed bug when directory size became larger than 1 block
- - fixed bug (for single client case) when PWD was deleted
- - invalidate local directory pages when doing intent-based ops
- - avoid LDLM oops when lock callback contained bad data
-
-2002-09-09 Andreas Dilger <adilger@clusterfs.com>
- * version 0_5_7
- * documentation updates
- * bug fixes and cleanups
- - configuration tools
- - LOV
- - imports/exports
- - 64-bit compile warnings
- - 64-bit internal statfs data
- - many more
- * test_brw on persistent OST devices
- * MDS recovery
- * lprocfs (disabled)
-
-2002-09-04 Andreas Dilger <adilger@clusterfs.com>
- * version 0_5_6
- * documentation updates
- * bug fixes and cleanups
- * configuration tools
-
-2002-08-30 Peter J. Braam <braam@clusterfs.com>
-
- * version v0_5_5
- * many small fixes to 0_5_4
- * io/network handling
- * thinkos in MDS operations
-
-2002-08-24 Peter J. Braam <braam@clusterfs.com>
-
- * version v0_5_4
- * crucial basic fixes to 0.5.3
- * IOR, Iozone work over Elan
- * EOF locks added
-
-2002-08-07 Phil Schwan <phil@clusterfs.com>
- * version 0_5_3, our first alpha
- * we use the new Portals iovs
- * documentation updates
- * bug fixes and cleanups
- * small changes in the DLM wire protocol
-
-2002-07-25 Peter J. Braam <braam@clusterfs.com>
- * version 0_5_1 with some initial stability,
- * locking on MD and file I/O.
- * documentation updates
- * several bug fixes since 0.5.0
- * small changes in wire protocol
-
-2002-07-18 Phil Schwan <phil@clusterfs.com>
- * version v0_4_5
- * delivered as Lustre Light Alpha
- * fixed a crash after handling invalid MDS requests
- * fixed directory pages for architectures with non-4k pages sizes
-
-2002-07-11 Andreas Dilger <adilger@clusterfs.com>
- * release version v0_4_4
- * Moves TCP acceptor to be on port 2432 (unused Coda port) instead
- of 1234.
- * Fixes a number of interruption problems with OST operations.
- * Update documentation for portals header changes
- * Move all wire protocol structs/defines to lustre_idl.h
- * Fixes symlink length bug.
- * Add tcpdump to repository.
-
-2002-07-05 Andreas Dilger <adilger@clusterfs.com>
- * release version v0_4_3
- * Fixes statfs for inodes on extN.
- * Fixes bug in runtests which would delete /etc/hosts.
- * Use 64-bit object IDs wherever possible (not into VFS though)
- Remove ost_get_info, which is unused by lustre, and out of date.
-
-2002-07-03 Peter Braam <braam@clusterfs.com>
- * release version v0_4_2 Fixes a lookup error (type not passed)
- * move forward to head of Portals
- * move forward to latest Lustre kernel
-
-2002-06-25 Peter Braam <braam@clusterfs.com>
- * release version v0_4_1. Hopefully stable on single node use.
+++ /dev/null
- GNU Free Documentation License
- Version 1.1, March 2000
-
- Copyright (C) 2000 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.
-
-
-0. PREAMBLE
-
-The purpose of this License is to make a manual, textbook, or other
-written document "free" in the sense of freedom: to assure everyone
-the effective freedom to copy and redistribute it, with or without
-modifying it, either commercially or noncommercially. Secondarily,
-this License preserves for the author and publisher a way to get
-credit for their work, while not being considered responsible for
-modifications made by others.
-
-This License is a kind of "copyleft", which means that derivative
-works of the document must themselves be free in the same sense. It
-complements the GNU General Public License, which is a copyleft
-license designed for free software.
-
-We have designed this License in order to use it for manuals for free
-software, because free software needs free documentation: a free
-program should come with manuals providing the same freedoms that the
-software does. But this License is not limited to software manuals;
-it can be used for any textual work, regardless of subject matter or
-whether it is published as a printed book. We recommend this License
-principally for works whose purpose is instruction or reference.
-
-
-1. APPLICABILITY AND DEFINITIONS
-
-This License applies to any manual or other work that contains a
-notice placed by the copyright holder saying it can be distributed
-under the terms of this License. The "Document", below, refers to any
-such manual or work. Any member of the public is a licensee, and is
-addressed as "you".
-
-A "Modified Version" of the Document means any work containing the
-Document or a portion of it, either copied verbatim, or with
-modifications and/or translated into another language.
-
-A "Secondary Section" is a named appendix or a front-matter section of
-the Document that deals exclusively with the relationship of the
-publishers or authors of the Document to the Document's overall subject
-(or to related matters) and contains nothing that could fall directly
-within that overall subject. (For example, if the Document is in part a
-textbook of mathematics, a Secondary Section may not explain any
-mathematics.) The relationship could be a matter of historical
-connection with the subject or with related matters, or of legal,
-commercial, philosophical, ethical or political position regarding
-them.
-
-The "Invariant Sections" are certain Secondary Sections whose titles
-are designated, as being those of Invariant Sections, in the notice
-that says that the Document is released under this License.
-
-The "Cover Texts" are certain short passages of text that are listed,
-as Front-Cover Texts or Back-Cover Texts, in the notice that says that
-the Document is released under this License.
-
-A "Transparent" copy of the Document means a machine-readable copy,
-represented in a format whose specification is available to the
-general public, whose contents can be viewed and edited directly and
-straightforwardly with generic text editors or (for images composed of
-pixels) generic paint programs or (for drawings) some widely available
-drawing editor, and that is suitable for input to text formatters or
-for automatic translation to a variety of formats suitable for input
-to text formatters. A copy made in an otherwise Transparent file
-format whose markup has been designed to thwart or discourage
-subsequent modification by readers is not Transparent. A copy that is
-not "Transparent" is called "Opaque".
-
-Examples of suitable formats for Transparent copies include plain
-ASCII without markup, Texinfo input format, LaTeX input format, SGML
-or XML using a publicly available DTD, and standard-conforming simple
-HTML designed for human modification. Opaque formats include
-PostScript, PDF, proprietary formats that can be read and edited only
-by proprietary word processors, SGML or XML for which the DTD and/or
-processing tools are not generally available, and the
-machine-generated HTML produced by some word processors for output
-purposes only.
-
-The "Title Page" means, for a printed book, the title page itself,
-plus such following pages as are needed to hold, legibly, the material
-this License requires to appear in the title page. For works in
-formats which do not have any title page as such, "Title Page" means
-the text near the most prominent appearance of the work's title,
-preceding the beginning of the body of the text.
-
-
-2. VERBATIM COPYING
-
-You may copy and distribute the Document in any medium, either
-commercially or noncommercially, provided that this License, the
-copyright notices, and the license notice saying this License applies
-to the Document are reproduced in all copies, and that you add no other
-conditions whatsoever to those of this License. You may not use
-technical measures to obstruct or control the reading or further
-copying of the copies you make or distribute. However, you may accept
-compensation in exchange for copies. If you distribute a large enough
-number of copies you must also follow the conditions in section 3.
-
-You may also lend copies, under the same conditions stated above, and
-you may publicly display copies.
-
-
-3. COPYING IN QUANTITY
-
-If you publish printed copies of the Document numbering more than 100,
-and the Document's license notice requires Cover Texts, you must enclose
-the copies in covers that carry, clearly and legibly, all these Cover
-Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
-the back cover. Both covers must also clearly and legibly identify
-you as the publisher of these copies. The front cover must present
-the full title with all words of the title equally prominent and
-visible. You may add other material on the covers in addition.
-Copying with changes limited to the covers, as long as they preserve
-the title of the Document and satisfy these conditions, can be treated
-as verbatim copying in other respects.
-
-If the required texts for either cover are too voluminous to fit
-legibly, you should put the first ones listed (as many as fit
-reasonably) on the actual cover, and continue the rest onto adjacent
-pages.
-
-If you publish or distribute Opaque copies of the Document numbering
-more than 100, you must either include a machine-readable Transparent
-copy along with each Opaque copy, or state in or with each Opaque copy
-a publicly-accessible computer-network location containing a complete
-Transparent copy of the Document, free of added material, which the
-general network-using public has access to download anonymously at no
-charge using public-standard network protocols. If you use the latter
-option, you must take reasonably prudent steps, when you begin
-distribution of Opaque copies in quantity, to ensure that this
-Transparent copy will remain thus accessible at the stated location
-until at least one year after the last time you distribute an Opaque
-copy (directly or through your agents or retailers) of that edition to
-the public.
-
-It is requested, but not required, that you contact the authors of the
-Document well before redistributing any large number of copies, to give
-them a chance to provide you with an updated version of the Document.
-
-
-4. MODIFICATIONS
-
-You may copy and distribute a Modified Version of the Document under
-the conditions of sections 2 and 3 above, provided that you release
-the Modified Version under precisely this License, with the Modified
-Version filling the role of the Document, thus licensing distribution
-and modification of the Modified Version to whoever possesses a copy
-of it. In addition, you must do these things in the Modified Version:
-
-A. Use in the Title Page (and on the covers, if any) a title distinct
- from that of the Document, and from those of previous versions
- (which should, if there were any, be listed in the History section
- of the Document). You may use the same title as a previous version
- if the original publisher of that version gives permission.
-B. List on the Title Page, as authors, one or more persons or entities
- responsible for authorship of the modifications in the Modified
- Version, together with at least five of the principal authors of the
- Document (all of its principal authors, if it has less than five).
-C. State on the Title page the name of the publisher of the
- Modified Version, as the publisher.
-D. Preserve all the copyright notices of the Document.
-E. Add an appropriate copyright notice for your modifications
- adjacent to the other copyright notices.
-F. Include, immediately after the copyright notices, a license notice
- giving the public permission to use the Modified Version under the
- terms of this License, in the form shown in the Addendum below.
-G. Preserve in that license notice the full lists of Invariant Sections
- and required Cover Texts given in the Document's license notice.
-H. Include an unaltered copy of this License.
-I. Preserve the section entitled "History", and its title, and add to
- it an item stating at least the title, year, new authors, and
- publisher of the Modified Version as given on the Title Page. If
- there is no section entitled "History" in the Document, create one
- stating the title, year, authors, and publisher of the Document as
- given on its Title Page, then add an item describing the Modified
- Version as stated in the previous sentence.
-J. Preserve the network location, if any, given in the Document for
- public access to a Transparent copy of the Document, and likewise
- the network locations given in the Document for previous versions
- it was based on. These may be placed in the "History" section.
- You may omit a network location for a work that was published at
- least four years before the Document itself, or if the original
- publisher of the version it refers to gives permission.
-K. In any section entitled "Acknowledgements" or "Dedications",
- preserve the section's title, and preserve in the section all the
- substance and tone of each of the contributor acknowledgements
- and/or dedications given therein.
-L. Preserve all the Invariant Sections of the Document,
- unaltered in their text and in their titles. Section numbers
- or the equivalent are not considered part of the section titles.
-M. Delete any section entitled "Endorsements". Such a section
- may not be included in the Modified Version.
-N. Do not retitle any existing section as "Endorsements"
- or to conflict in title with any Invariant Section.
-
-If the Modified Version includes new front-matter sections or
-appendices that qualify as Secondary Sections and contain no material
-copied from the Document, you may at your option designate some or all
-of these sections as invariant. To do this, add their titles to the
-list of Invariant Sections in the Modified Version's license notice.
-These titles must be distinct from any other section titles.
-
-You may add a section entitled "Endorsements", provided it contains
-nothing but endorsements of your Modified Version by various
-parties--for example, statements of peer review or that the text has
-been approved by an organization as the authoritative definition of a
-standard.
-
-You may add a passage of up to five words as a Front-Cover Text, and a
-passage of up to 25 words as a Back-Cover Text, to the end of the list
-of Cover Texts in the Modified Version. Only one passage of
-Front-Cover Text and one of Back-Cover Text may be added by (or
-through arrangements made by) any one entity. If the Document already
-includes a cover text for the same cover, previously added by you or
-by arrangement made by the same entity you are acting on behalf of,
-you may not add another; but you may replace the old one, on explicit
-permission from the previous publisher that added the old one.
-
-The author(s) and publisher(s) of the Document do not by this License
-give permission to use their names for publicity for or to assert or
-imply endorsement of any Modified Version.
-
-
-5. COMBINING DOCUMENTS
-
-You may combine the Document with other documents released under this
-License, under the terms defined in section 4 above for modified
-versions, provided that you include in the combination all of the
-Invariant Sections of all of the original documents, unmodified, and
-list them all as Invariant Sections of your combined work in its
-license notice.
-
-The combined work need only contain one copy of this License, and
-multiple identical Invariant Sections may be replaced with a single
-copy. If there are multiple Invariant Sections with the same name but
-different contents, make the title of each such section unique by
-adding at the end of it, in parentheses, the name of the original
-author or publisher of that section if known, or else a unique number.
-Make the same adjustment to the section titles in the list of
-Invariant Sections in the license notice of the combined work.
-
-In the combination, you must combine any sections entitled "History"
-in the various original documents, forming one section entitled
-"History"; likewise combine any sections entitled "Acknowledgements",
-and any sections entitled "Dedications". You must delete all sections
-entitled "Endorsements."
-
-
-6. COLLECTIONS OF DOCUMENTS
-
-You may make a collection consisting of the Document and other documents
-released under this License, and replace the individual copies of this
-License in the various documents with a single copy that is included in
-the collection, provided that you follow the rules of this License for
-verbatim copying of each of the documents in all other respects.
-
-You may extract a single document from such a collection, and distribute
-it individually under this License, provided you insert a copy of this
-License into the extracted document, and follow this License in all
-other respects regarding verbatim copying of that document.
-
-
-7. AGGREGATION WITH INDEPENDENT WORKS
-
-A compilation of the Document or its derivatives with other separate
-and independent documents or works, in or on a volume of a storage or
-distribution medium, does not as a whole count as a Modified Version
-of the Document, provided no compilation copyright is claimed for the
-compilation. Such a compilation is called an "aggregate", and this
-License does not apply to the other self-contained works thus compiled
-with the Document, on account of their being thus compiled, if they
-are not themselves derivative works of the Document.
-
-If the Cover Text requirement of section 3 is applicable to these
-copies of the Document, then if the Document is less than one quarter
-of the entire aggregate, the Document's Cover Texts may be placed on
-covers that surround only the Document within the aggregate.
-Otherwise they must appear on covers around the whole aggregate.
-
-
-8. TRANSLATION
-
-Translation is considered a kind of modification, so you may
-distribute translations of the Document under the terms of section 4.
-Replacing Invariant Sections with translations requires special
-permission from their copyright holders, but you may include
-translations of some or all Invariant Sections in addition to the
-original versions of these Invariant Sections. You may include a
-translation of this License provided that you also include the
-original English version of this License. In case of a disagreement
-between the translation and the original English version of this
-License, the original English version will prevail.
-
-
-9. TERMINATION
-
-You may not copy, modify, sublicense, or distribute the Document except
-as expressly provided for under this License. Any other attempt to
-copy, modify, sublicense or distribute the Document 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.
-
-
-10. FUTURE REVISIONS OF THIS LICENSE
-
-The Free Software Foundation may publish new, revised versions
-of the GNU Free Documentation 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. See
-http://www.gnu.org/copyleft/.
-
-Each version of the License is given a distinguishing version number.
-If the Document specifies that a particular numbered version of this
-License "or any later version" applies to it, you have the option of
-following the terms and conditions either of that specified version or
-of any later version that has been published (not as a draft) by the
-Free Software Foundation. If the Document does not specify a version
-number of this License, you may choose any version ever published (not
-as a draft) by the Free Software Foundation.
-
-
-ADDENDUM: How to use this License for your documents
-
-To use this License in a document you have written, include a copy of
-the License in the document and put the following copyright and
-license notices just after the title page:
-
- Copyright (c) YEAR YOUR NAME.
- Permission is granted to copy, distribute and/or modify this document
- under the terms of the GNU Free Documentation License, Version 1.1
- or any later version published by the Free Software Foundation;
- with the Invariant Sections being LIST THEIR TITLES, with the
- Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
- A copy of the license is included in the section entitled "GNU
- Free Documentation License".
-
-If you have no Invariant Sections, write "with no Invariant Sections"
-instead of saying which ones are invariant. If you have no
-Front-Cover Texts, write "no Front-Cover Texts" instead of
-"Front-Cover Texts being LIST"; likewise for Back-Cover Texts.
-
-If your document contains nontrivial examples of program code, we
-recommend releasing these examples in parallel under your choice of
-free software license, such as the GNU General Public License,
-to permit their use in free software.
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-AUTOMAKE_OPTIONS = foreign
-
-if LINUX25
-DIRS24 = mds
-else
-DIRS24 = extN mds
-endif
-
-# NOTE: keep extN before mds and obdfilter
-SUBDIRS = $(DIRS24) obdclass utils ptlrpc ldlm lib obdfilter mdc osc ost llite
-SUBDIRS+= obdecho lov tests doc scripts
-
-DIST_SUBDIRS = $(SUBDIRS)
-EXTRA_DIST = BUGS FDL Rules include patches archdep.m4
-
-# We get the version from the spec file.
-CONFIGURE_DEPENDENCIES = scripts/lustre.spec.in
-
-dist-hook:
- find $(distdir) -name .deps | xargs rm -rf
- find $(distdir) -name CVS | xargs rm -rf
-
-include $(top_srcdir)/Rules
-
-rpms: dist Makefile
- rpm -ta $(distdir).tar.gz
+++ /dev/null
-Instructions for building, configuring, and running Lustre can be found in
-the file doc/lustre-HOWTO.txt.
-
-If you have checked lustre directly out of CVS, then you either need to
-get lyx to build the lustre-HOWTO.txt from the source file, get the PDF
-version from the lustre.org website, or install the lustre-doc RPM for
-the formatted text version (or read the somewhat cryptic lustre-HOWTO.lin
-file if you are desperate).
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-# Build a kernel module, name.o, and install it in $(moduledir) by:
-# MODULE = name
-# module_DATA = name.o
-# EXTRA_PROGRAMS = name
-# name_SOURCES = my.c files.c
-# include $(top_srcdir)/Rules
-
-$(MODULE).o: $($(MODULE)_OBJECTS)
- $(LD) -m "`$(LD) --help | awk '/supported emulations/ {print $$4}'`" -r -o $(MODULE).o $($(MODULE)_OBJECTS)
-
-tags:
- rm -f $(top_srcdir)/TAGS
- rm -f $(top_srcdir)/tags
- find $(top_srcdir)/../portals/ -name '*.[hc]' | xargs etags -a
- find $(top_srcdir) -name '*.[hc]' | xargs etags -a
- find $(top_srcdir)/../portals/ -name '*.[hc]' | xargs ctags -a
- find $(top_srcdir) -name '*.[hc]' | xargs ctags -a
-
-AM_CPPFLAGS="-I$(top_builddir)/include"
+++ /dev/null
-AC_MSG_CHECKING(if you are running user mode linux for $host_cpu ...)
-if test -e $LINUX/include/asm-um ; then
-if test X`ls -id $LINUX/include/asm/ | awk '{print $1}'` = X`ls -id $LINUX/include/asm-um | awk '{print $1}'` ; then
- host_cpu="um";
- AC_MSG_RESULT(yes)
-else
- AC_MSG_RESULT(no (asm doesn't point at asm-um))
-fi
-
-else
- AC_MSG_RESULT(no (asm-um missing))
-fi
-
-AC_MSG_CHECKING(setting make flags system architecture: )
-case ${host_cpu} in
- um )
- AC_MSG_RESULT($host_cpu)
- KCFLAGS='-g -Wall -pipe -Wno-trigraphs -Wstrict-prototypes -fno-strict-aliasing -fno-common '
- KCPPFLAGS='-D__KERNEL__ -U__i386__ -Ui386 -DUM_FASTCALL -D__arch_um__ -DSUBARCH="i386" -DNESTING=0 -D_LARGEFILE64_SOURCE -Derrno=kernel_errno -DPATCHLEVEL=4 -DMODULE -I$(LINUX)/arch/um/include '
- MOD_LINK=elf_i386
-;;
- i*86 )
- AC_MSG_RESULT($host_cpu)
- KCFLAGS='-g -O2 -Wall -Wstrict-prototypes -pipe'
- KCPPFLAGS='-D__KERNEL__ -DMODULE '
- MOD_LINK=elf_i386
-;;
-
- alphaev6 )
- AC_MSG_RESULT($host_cpu)
- KCFLAGS='-g -O2 -Wall -Wstrict-prototypes -Wno-trigraphs -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mno-fp-regs -ffixed-8 -mcpu=ev5 -Wa,-mev6'
- KCPPFLAGS='-D__KERNEL__ -DMODULE '
- MOD_LINK=elf64alpha
-;;
-
- alphaev67 )
- AC_MSG_RESULT($host_cpu)
- KCFLAGS='-g -O2 -Wall -Wstrict-prototypes -Wno-trigraphs -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mno-fp-regs -ffixed-8 -mcpu=ev5 -Wa,-mev6'
- KCPPFLAGS='-D__KERNEL__ -DMODULE '
- MOD_LINK=elf64alpha
-;;
-
- alpha* )
- AC_MSG_RESULT($host_cpu)
- KCFLAGS='-g -O2 -Wall -Wstrict-prototypes -Wno-trigraphs -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mno-fp-regs -ffixed-8 -mcpu=ev5 -Wa,-mev5'
- KCPPFLAGS='-D__KERNEL__ -DMODULE '
- MOD_LINK=elf64alpha
-;;
-
- ia64 )
- AC_MSG_RESULT($host_cpu)
- KCFLAGS='-g -O2 -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -pipe -ffixed-r13 -mfixed-range=f10-f15,f32-f127 -falign-functions=32 -mb-step'
- KCPPFLAGS='-D__KERNEL__ -DMODULE'
- MOD_LINK=elf64_ia64
-;;
-
- sparc64 )
- AC_MSG_RESULT($host_cpu)
- KCFLAGS='-O2 -Wall -Wstrict-prototypes -Wno-trigraphs -fomit-frame-pointer -fno-strict-aliasing -fno-common -Wno-unused -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare -Wa,--undeclared-regs'
- KCPPFLAGS='-D__KERNEL__'
- MOD_LINK=elf64_sparc
-
-;;
-
- powerpc )
- AC_MSG_RESULT($host_cpu)
- KCFLAGS='-O2 -Wall -Wstrict-prototypes -Wno-trigraphs -fomit-frame-pointer -fno-strict-aliasing -fno-common -D__powerpc__ -fsigned-char -msoft-float -pipe -ffixed-r2 -Wno-uninitialized -mmultiple -mstring'
- KCPPFLAGS='-D__KERNEL__'
- MOD_LINK=elf32ppclinux
-;;
-
- *)
- AC_ERROR("Unknown Linux Platform: $host_cpu")
-;;
-esac
-
-AC_MSG_CHECKING(for MODVERSIONS)
-if egrep -e 'MODVERSIONS.*1' $LINUX/include/linux/autoconf.h >/dev/null 2>&1;
-then
- MFLAGS="-DMODULE -DMODVERSIONS -include $LINUX/include/linux/modversions.h -DEXPORT_SYMTAB"
- AC_MSG_RESULT(yes)
-else
- MFLAGS=
- AC_MSG_RESULT(no)
-fi
-
-AC_MSG_CHECKING(for SMP)
-if egrep -e SMP=y $LINUX/.config >/dev/null 2>&1; then
- SMPFLAG=
- AC_MSG_RESULT(yes)
-else
- SMPFLAG=
- AC_MSG_RESULT(no)
-fi
-
-CFLAGS="$KCFLAGS $MFLAGS"
-ARCHCPPFLAGS="$KCPPFLAGS"
+++ /dev/null
-#!/bin/sh
-
-find . -type d -name .deps | xargs rm -rf
-aclocal &&
-automake --add-missing &&
-${AUTOCONF:-autoconf}
+++ /dev/null
-AC_INIT
-AC_CANONICAL_SYSTEM
-
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-# Automake variables. Steal the version number from lustre.spec.in.
-AM_INIT_AUTOMAKE(lustre, builtin([esyscmd], [sed -ne '/^%define version /{ s/.*version //; p; q; }' scripts/lustre.spec.in]))
-#AM_MAINTAINER_MODE
-AC_PROG_CC
-AC_PROG_RANLIB
-
-#
-# Check for required packages
-
-# this doesn't seem to work on older autoconf
-# AC_CHECK_LIB(readline, readline,,)
-
-AC_ARG_ENABLE(readline, [ --enable-readline use readline library],,
- enable_readline="yes")
-
-if test "$enable_readline" = "yes" ; then
- LIBREADLINE="-lreadline -lncurses"
- HAVE_LIBREADLINE="-DHAVE_LIBREADLINE=1"
-else
- LIBREADLINE=""
- HAVE_LIBREADLINE=""
-fi
-AC_SUBST(LIBREADLINE)
-AC_SUBST(HAVE_LIBREADLINE)
-
-# Kernel build environment.
-ac_default_prefix=
-bindir='${exec_prefix}/usr/bin'
-sbindir='${exec_prefix}/usr/sbin'
-
-linuxdir_def=/usr/src/linux
-AC_ARG_WITH(linux, [ --with-linux=[path] set path to Linux source (default=/usr/src/linux)], enable_linuxdir=$withval)
-AC_ARG_ENABLE(linuxdir, [ --enable-linuxdir=[path] (deprecated) set path to Linux source (default=/usr/src/linux)],, enable_linuxdir=$linuxdir_def)
-
-LINUX=$enable_linuxdir
-AC_SUBST(LINUX)
-
-sinclude(archdep.m4)
-
-AC_MSG_CHECKING(if you are running linux 2.5...)
-if test -e $LINUX/include/linux/namei.h ; then
- linux25=yes
- AC_MSG_RESULT(yes)
-else
- linux25=no
- AC_MSG_RESULT(no)
-fi
-AM_CONDITIONAL(LINUX25, test x$linux25 = xyes)
-
-KINCFLAGS='-I. -I$(top_srcdir)/include -I$(PORTALS)/include -I$(LINUX)/include'
-CPPFLAGS="$KINCFLAGS $ARCHCPPFLAGS"
-
-portalsdir_def='$(top_srcdir)/../portals'
-AC_ARG_WITH(portals, [ --with-portals=[path] set path to Portals source (default=../portals)], enable_portalsdir=$withval)
-AC_ARG_ENABLE(portalsdir, [ --enable-portalsdir=[path] (deprecated) set path to Portals source (default=$(top_srcdir)/../portals)],, enable_portalsdir=$portalsdir_def)
-PORTALS=$enable_portalsdir
-AC_SUBST(PORTALS)
-
-portalslib_def=$enable_portalsdir/linux/utils
-AC_ARG_WITH(portalslib, [ --with-portalslib=[path] set path to Portals library (default=../portals/linux/utils)], enable_portalslib=$withval)
-AC_ARG_ENABLE(portalslib, [ --enable-portalslib=[path] (deprecated) set path to Portals lib (default=../portals/linux/utils)],, enable_portalslib=$portalslib_def)
-
-
-if ! test -z "$enable_portalslib"; then
- PORTALSLIB=${enable_portalslib}
-fi
-
-
-AC_SUBST(PORTALSLIB)
-
-AC_MSG_CHECKING(if make dep has been run in kernel source)
-if test -f $LINUX/include/linux/config.h ; then
- AC_MSG_RESULT(yes)
-else
- AC_MSG_ERROR(** cannot find $LINUX/include/linux/config.h. Run make dep in $LINUX.)
-fi
-
-AC_MSG_CHECKING(if autoconf.h is in kernel source)
-if test -f $LINUX/include/linux/autoconf.h ; then
- AC_MSG_RESULT(yes)
-else
- AC_MSG_ERROR(** cannot find $LINUX/include/linux/autoconf.h. Run make config in $LINUX.)
-fi
-
-
-AC_MSG_CHECKING(for Linux release)
-
-dnl We need to rid ourselves of the nasty [ ] quotes.
-changequote(, )
-dnl Get release from version.h
-RELEASE="`sed -ne 's/.*UTS_RELEASE[ \"]*\([0-9.a-zA-Z-]*\).*/\1/p' $LINUX/include/linux/version.h`"
-changequote([, ])
-
-moduledir='$(libdir)/modules/'$RELEASE/kernel
-AC_SUBST(moduledir)
-
-modulefsdir='$(moduledir)/fs/$(PACKAGE)'
-AC_SUBST(modulefsdir)
-
-AC_MSG_RESULT($RELEASE)
-AC_SUBST(RELEASE)
-
-# Directories for documentation and demos.
-docdir='${prefix}/usr/share/doc/$(PACKAGE)'
-AC_SUBST(docdir)
-
-demodir='$(docdir)/demo'
-AC_SUBST(demodir)
-
-# not needed until the AC_CHECK_LIB(readline) above works
-# AM_CONFIG_HEADER(include/config.h)
-
-AC_OUTPUT(Makefile lib/Makefile ldlm/Makefile obdecho/Makefile ptlrpc/Makefile \
- lov/Makefile osc/Makefile mdc/Makefile mds/Makefile ost/Makefile \
- utils/Makefile tests/Makefile obdfilter/Makefile obdclass/Makefile \
- llite/Makefile doc/Makefile scripts/Makefile \
- scripts/lustre.spec extN/Makefile)
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-tags
-TAGS
-OBD-HOWTO.html
-OBD-HOWTO.txt
-lustre-HOWTO.lyx
-lustre-HOWTO.txt
-lustre-pdf.bbl
-lustre-pdf.blg
-lustre-pdf.log
-lustre-pdf.out
-lustre-pdf.toc
-*.eps
-lustre.lyx
-*.tex
-*.pdf
-*.aux
+++ /dev/null
-# Copyright (C) 2001, 2002 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-LYX2PDF = GS_OPTIONS=-dCompatibilityLevel=1.1 $(srcdir)/tex2pdf -overwrite
-TEX2PDF = GS_OPTIONS=-dCompatibilityLevel=1.1 $(srcdir)/tex2pdf -overwrite
-LYX2PS = lyx --export ps
-LYX2TEX = lyx --export latex
-LYX2TXT = lyx --export text
-LYX2HTML = lyx --export html
-LATEX = latex
-DVIPS = dvips
-PS2PDF = ps2pdf
-TEXEXPAND = texexpand
-SUFFIXES = .lin .lyx .pdf .ps .sgml .html .txt .tex .fig .eps .dvi
-
-DOCS = lustre.pdf lustre-HOWTO.txt
-HOWTODOC = lustre-HOWTO.txt
-IMAGES := $(patsubst %.fig,%.eps,$(wildcard *.fig))
-LYXFILES= $(filter-out $(patsubst %.lin,%.lyx,$(wildcard *.lin)),\
- $(wildcard *.lin *.lyx))
-
-MAINTAINERCLEANFILES = $(IMAGES) $(DOCS) $(VERSIONED)
-CLEANFILES = *.aux *.tex doc.old/*.aux doc.old/*.tex *.eps *.log *.pdf
-VERSIONED = lustre-HOWTO.lyx lustre.lyx doc.old/lustre-HOWTO.lyx doc.old/lustre.lyx
-GENERATED = $(VERSIONED) lustre-full.tex lustre-chbar.tex
-
-EXTRA_DIST = chbar.sh postbar tex2pdf $(DOCS) $(IMAGES) $(LYXFILES) lustre.bib
-
-all: $(HOWTODOC)
-docs: $(DOCS)
-
-# These variables are set by lbuild/check-build.
-RPMRELEASE ?= RELEASE
-KERNTYPE ?= chaos
-KERNRPM ?= kernel-2.4.18lustre13-RELEASE.i386.rpm
-
-# update date and version in document
-date := $(shell date +%x)
-tag := $(shell echo '$$Name: $$' | sed -e 's/^\$$Na''me: *\$$$$/HEAD/; s/^\$$Na''me: \(.*\) \$$$$/\1/')
-addversion = sed -e 's|@T''AG@|$(tag)|g; s|@VER''SION@|$(VERSION)|g; s|@DA''TE@|$(date)|g; s|@RPM''RELEASE@|$(RPMRELEASE)|g; s|@KERN''TYPE@|$(KERNTYPE)|g; s|@KERN''RPM@|$(KERNRPM)|g'
-
-# Regenerate when the $(VERSION) or $Name: $ changes.
-.INTERMEDIATE: $(GENERATED)
-$(VERSIONED) : %.lyx: %.lin Makefile
- $(addversion) $< > $@
-
-.lyx.pdf:
- @echo $(LYX2PDF) $< && $(LYX2PDF) $< || printf "\n*** Warning: not creating PDF docs; install lyx to rectify this\n"
-
-.lyx.ps:
- @echo $(LYX2PS) $< && $(LYX2PS) $< || printf "\n*** Warning: not creating PostScript docs; install lyx to rectify this\n"
-
-.lyx.tex:
- @echo $(LYX2TEX) $< && $(LYX2TEX) $< || printf "\n*** Warning: not creating LaTeX docs; install lyx to rectify this\n"
-
-.lyx.txt:
- @echo $(LYX2TXT) $< && $(LYX2TXT) $< || printf "\n*** Warning: not creating text docs; install lyx to rectify this\n"
-
-.lyx.html:
- @echo $(LYX2HTML) $< && $(LYX2HTML) $< || printf "\n*** Warning: not creating HTML docs; install lyx to rectify this\n"
-
-.tex.pdf:
- $(TEX2PDF) $<
-
-.tex.dvi:
- $(LATEX) $<
- $(LATEX) $<
-
-.dvi.ps:
- $(DVIPS) $< -o $@
-
-.ps.pdf:
- $(PS2PDF) $< $@
-
-lustre.tex lustre.pdf lustre.txt lustre.html: $(IMAGES) $(LYXFILES) lustre-HOWTO.lyx
-.fig.eps:
- -fig2dev -L eps $< > $@
-
-syncweb: lustre.pdf
- cp lustre.pdf /usr/src/www/content/lustre/docs/lustre.pdf
- ( cd /usr/src/www ; make lustre ; make synclustre )
-.PHONY: syncweb chbar
-
-# Build a changebar document from the files in doc.old and this directory.
-chbar: lustre-chbar.pdf
-
-# FIXME: Temporary rules until pdftex displays changebars correctly.
-lustre-chbar.pdf: lustre-chbar-nopdf.ps
- $(PS2PDF) $< $@
-lustre-chbar-nopdf.ps: lustre-chbar-nopdf.dvi
- $(DVIPS) $< -o $@
-lustre-chbar-nopdf.dvi: lustre-chbar-nopdf.tex
- $(LATEX) $<
- $(LATEX) $<
-lustre-chbar-nopdf.tex: lustre-chbar.tex
- sed -e 's/^\(.*usepackage.*pdftex\)/%\1/' $< > $@
-
-%-chbar.tex: chbar.sh postbar doc.old/%-full.tex %-full.tex
- $(SHELL) $(srcdir)/chbar.sh doc.old/$*-full.tex $*-full.tex | $(srcdir)/postbar > $@
-
-# This rule needs to come before the next %-full.tex rule.
-doc.old/lustre.tex: doc.old/lustre-HOWTO.lyx
-doc.old/%-full.tex: doc.old/%.tex
- cd doc.old && $(TEXEXPAND) -texinputs=. -output=$*-full.tex $*.tex
-
-# This rule needs to come after the more specific doc.old rule.
-%-full.tex: %.tex
- $(TEXEXPAND) -texinputs=. -texinputs=$(srcdir) -output=$@ $<
-
-# Check out the old directory if it doesn't exist.
-doc.old/lustre.lin doc.old/lustre-HOWTO.lin:
- @if test "X$(OLD)" = X; then \
- echo "You must populate doc.old or specify a CVS tag like OLD=v0_5_1"; \
- exit 1; \
- fi
- rm -rf doc.old
- mkdir doc.old
- cvs checkout -r $(OLD) -d doc.old lustre/doc
-
-dist-hook:
- rm -rf $(distdir)/figs/CVS
-
-include $(top_srcdir)/Rules
+++ /dev/null
-Lustre versioning
-=================
-
-0.0.1 2/19/2002 <braam@clusterfs.com>
-0.0.2 3/14/2002 <braam@clusterfs.com> describe branches / stable tag
-0.0.3 6/10/2002 <braam@clusterfs.com> describe release mechanisms
-
-This document describes versioning of source and binaries for Lustre.
-
-Packages
-========
-
-RPM's that you build should get 3 figure versions, CVS versions will
-be 4 digits, and can correspond to test RPM's, and lead up to the
-package version. So let's plan on releasing
-
-So you'd build 2 sets of test rpms this week:
-
-0.0.9.1
-0.0.9.2
-
-we decide it's fine then and we release
-
-0.1.0
-
-We go on developing with
-
-0.1.0.{1,2,3,4,...}
-
-as test releases and then we release:
-
-0.1.1
-
-The 0.1 sequence is an unstable sequence, like 2.5 for the kernel is.
-So we expect lots of 0.1.X releases leading up to a stable 0.2 (or
-1.0) at the time of deployment.
-
-CVS
-===
-
-Versions will have 4 digits:
- major.minor.patch.test
-
-Such versions will be tagged in CVS as:
- v1_2_11_7
-and referred to as:
- 1.2.11.7
-encoded as:
- 0x01021107
-
-Usage:
-------
-
-New numbers are used as follows:
-
-1. major:
- - increased when major new functionality becomes available
-2. minor:
- - even: for each new release with new functionality
- - odd : when a new development cycle starts after a release
-3. patch:
- - when a development snapshot or release update becomes available
- - all these are announced on lustre-devel@lists.sf.net
-4. test:
- - when developers feel it is time to exchange a named version
-
-What will run, what won't ?
----------------------------
-
-1. If the test level is non-zero, i.e. there are 4 digits in the
- version, no guarantees of any kind are made.
-
-2. For three digit releases/tags the code should perform
- according to the announcement.
-
-Moving tags
------------
-
-The last stable release will be tagged: CVS tag "t_last_stable"
-The last operational development snapshot will be CVS tag "dstable"
-
-Branches
---------
-
-Any and all development must be done on branches, and can only merge to the
-HEAD if _at_least_ tests/acceptance-small.sh and IOR with 5 SMP nodes and
-2 clients/node with 1GB file/client pass without any errors or cleanup
-problems. Additional tests may be added in the future, so the tests in the
-current CVS head must pass before a branch can be merged back to the trunk.
-
-See http://lustre.org/docs/branches.html for details on CVS branch usage.
+++ /dev/null
-#!/bin/sh
-# Gadget to take two LaTeX files and produce a third which
-# has changebars highlighting the difference between them.
-#
-# Version 1.2
-# Author:
-# Don Ward, Careful Computing (don@careful.co.uk)
-# v1.0 April 1989
-# v1.1 Feb 93 Amended to use changebar.sty (v3.0) and dvips
-# v1.2 Aug 95 Added support for LaTeX209/LaTeX2e
-# Added RCS support to retrive old files
-
-CMD=`basename $0`
-
-SED=sed
-RM="rm -f"
-DIFF=diff
-ED=ed
-AWK=awk
-GREP=grep
-MV=mv
-CAT=cat
-MKDIR=mkdir
-CO="co"
-
-TMPDIR=${TMP-/tmp}/$CMD.$$
-trap 'test $DEBUG = NO && rm -rf $TMPDIR' 0 1 2 3 6 7 13 15
-mkdir $TMPDIR || { echo "cannot create directory \`$TMPDIR'." >&2; exit 1; }
-TMPFILE=${TMPDIR}/$CMD.$$
-SED_CMD_FILE=$TMPFILE.sed
-
-usage()
-{
-$CAT << _END_
-Usage:
- $CMD [-hgG] [-d dir] old new [output]
- default output is stdout
-
- $CMD [-hgG] [-d dir] old
- new file on stdin, output on stdout
-
- $CMD [-hgG] -d dir -r rev files
- old file retrieved using RCS
-
- Gadget to take two LaTeX files and produce a third which
- has changebars highlighting the difference between them.
- Changebars are inserted for differences after '\begin{document}'.
-
- Feature: \`new' can not be named \`-'.
-
- Options are:
- -d dir : Write the output to file \`dir/new', if \`new' is given or
- to file \`dir/old'.
- If \`dir' does not exist, it is created.
- If \`output' is given, it is discarded.
-
- -r rev : If the LaTeX \`files' are kept under control of the
- Revision Control System RCS, the old files of
- the revision \`rev' can be retrived.
- \`rev' is specified using the RCS conventions.
- This option must be used together with the \`-d dir' option.
- \`files' must be a nonempty list of files.
-
- -h : Print this info text.
- -g : Print some debugging info.
- -G : Even more debug info.
-
- Version 1.2: August 3. 1995
-_END_
-exit 1
-}
-
-# parse options and arguments
-DEBUG="NO"
-DIR=
-REV=
-# process options
-while getopts d:r:gGh i $*
-do
- case $i in
- d ) DIR=$OPTARG;;
- r ) REV=$OPTARG;;
- g ) DEBUG="YES" ;;
- G ) set -x; DEBUG="YES";;
- h | \
- * ) usage ;;
- esac
-done
-
-shift `expr $OPTIND - 1`
-
-case $# in
- 1 ) OLD=$1; NEW="-"; OUT="" ;;
- 2 ) OLD=$1; NEW=$2; OUT="" ;;
- 3 ) OLD=$1; NEW=$2; OUT="$3" ;;
- * ) usage ;;
-esac
-
-# check correct options
-if [ ! -z "$DIR" ]
-then
- [ -d $DIR ] || $MKDIR $DIR
-fi
-
-if [ ! -z "$REV" ]
-then
- [ -z "$DIR" ] && usage
- FILES=$*
-else
- FILES=$NEW
-fi
-
-# do the work
-for NEW in $FILES
-do
- if [ ! -z "$DIR" ]
- then
- if [ $NEW = "-" ]
- then
- OUT=$DIR/$OLD
- else
- OUT=$DIR/$NEW
- fi
- fi
- if [ ! -z "$REV" ]
- then
- OLD=${TMPFILE}.old
- $CO -p"$REV" -q $NEW > $OLD
- fi
-
- [ $DEBUG = "YES" ] && echo "OLD=\`$OLD' NEW=\`$NEW' OUT=\`$OUT'"
-
- # gather some info about the file
- # Since we have for sure only the name of the OLD file, ...
- $GREP "^\\\\begin{document}" $OLD > /dev/null
- if [ $? -eq 0 ]
- then
- [ $DEBUG = "YES" ] && echo "contains a \\begin{document}"
- HAS_BEGIN_DOC="YES"
- else
- [ $DEBUG = "YES" ] && echo "contains no \\begin{document}"
- HAS_BEGIN_DOC="NO"
- fi
-
- # Method to do the work:
- # 1 Use diff to get an ed script to go from file1 to file2.
- # 2 Breath on it a bit (with sed) to insert changebar commands.
- # 3 Apply modified ed script to produce (nearly) the output.
- # 4 Use awk to insert the changebars option into the \documentstyle
- # and to handle changebar commands inside verbatim environments.
- # 5 Remove changebars before \begin{document} with sed
-
- # SED commands to edit ED commands to edit old file
- $CAT > $SED_CMD_FILE <<\_END_
-/^\.$/i\
-\\cbend{}%
-/^[0-9][0-9]*[ac]$/a\
-\\cbstart{}%
-/^[0-9][0-9]*,[0-9][0-9]*[ac]$/a\
-\\cbstart{}%
-/^[0-9][0-9]*d$/a\
-i\
-\\cbdelete{}%\
-.
-/^[0-9][0-9]*,[0-9][0-9]*d$/a\
-i\
-\\cbdelete{}%\
-.
-_END_
-
- # note DIFF accepts `-' as stdin
- $DIFF -b -e $OLD $NEW | \
- ( $SED -f $SED_CMD_FILE ; echo w ${TMPFILE}.1 ; echo q ) | \
- $ED - $OLD
-
- # AWK commands to insert Changebars style and to protect
- # changebar commands in verbatim environments
- # and to tell what driver is in use; we assume the `dvips' driver
-
- $AWK '
- BEGIN {kind=""; # we saw now \documentXXX[]{}
- }
- /^\\documentstyle/{
- kind = "209";
- if (index($0, "changebar") == 0 ) {
- opts = index($0, "[")
- if (opts > 0)
- printf "%schangebar,%s\n",substr($0,1,opts),substr($0,opts+1)
- else
- printf "\\documentstyle[changebar]%s\n", substr($0,15)
- next
- }
- }
- /^\\documentclass/{
- kind = "2e";
- printf "%s\n", $0
- printf "\\usepackage[dvips]{changebar}\n"
- next
- }
- /\\begin{document}/ {if (kind == "209" ) {print "\\driver{dvips}"}}
- /\\begin{verbatim}/{++nesting}
- /\\end{verbatim}/{--nesting}
- /\\cbstart{}%|\\cbend{}%|\cbdelete{}%/ {
- if ( nesting > 0) {
- # changebar command in a verbatim environment: Temporarily exit,
- # do the changebar command and reenter.
- #
- # The obvious ( printf "\\end{verbatim}%s\\begin{verbatim} , $0 )
- # leaves too much vertical space around the changed line(s).
- # The following magic seeems to work
- #
- print "\\end{verbatim}\\nointerlineskip"
- print "\\vskip -\\ht\\strutbox\\vskip -\\ht\\strutbox"
- printf "\\vbox to 0pt{\\vskip \\ht\\strutbox%s\\vss}\n", $0
- print "\\begin{verbatim}"
- next
- }
- }
- { print $0 }
- ' ${TMPFILE}.1 > ${TMPFILE}.2
-
- # if a \begin{document} is contained in the file,
- # remove the changebar commands before them
-
- if [ $HAS_BEGIN_DOC = "YES" ]
- then
- SED_CMD="1,/\\\\begin{document}/s/\(\\\\cb[sed][tne][adl][^{}]*{}%\)$/%%\1/"
- $SED "$SED_CMD" ${TMPFILE}.2 > ${TMPFILE}.3
- else
- $CAT ${TMPFILE}.2 > ${TMPFILE}.3
- fi
- if [ -z "$OUT" ]
- then
- $CAT ${TMPFILE}.3
- else
- $MV ${TMPFILE}.3 $OUT
- fi
-
-done
-
-[ $DEBUG = "NO" ] && $RM ${TMPFILE}.*
-
-###############################################################
+++ /dev/null
-#LyX 1.2 created this file. For more info see http://www.lyx.org/
-\lyxformat 220
-\textclass amsart
-\language english
-\inputencoding auto
-\fontscheme times
-\graphics default
-\paperfontsize default
-\spacing single
-\papersize letterpaper
-\paperpackage a4
-\use_geometry 0
-\use_amsmath 0
-\use_natbib 0
-\use_numerical_citations 0
-\paperorientation portrait
-\secnumdepth 3
-\tocdepth 3
-\paragraph_separation skip
-\defskip medskip
-\quotes_language english
-\quotes_times 2
-\papercolumns 1
-\papersides 1
-\paperpagestyle default
-
-\layout Section
-
-lconf
-\layout Subsection
-
-NAME
-\layout Standard
-
-lconf- Lustre file system configuration utility
-\layout Subsection
-
-SYNOPSIS
-\layout Standard
-
-
-\series bold
-lconf\SpecialChar ~
-[--node <node_name>] [-d,--cleanup] [--noexec] [--gdb] [--nosetup]
- [--nomod] [-n,--noexec] [-v,--verbose] [-h,--help] <XML-config file>
-\layout Subsection
-
-DESCRIPTION
-\layout Standard
-
-This program configures a node following directives in the <XML-config-file>
-\layout Description
-
---node\SpecialChar ~
-node_name Specifiy a specific node to configure.
- By default, LCONF will search for nodes with the local hostname and 'localhost'.
- When --node is used, only node_name is searched for.
- If a matching node is not found in the config, then LCONF exits with an
- error.
-\layout Description
-
---cleanup Unconfigure a node.
- The same config and --node argument used for configuration needs to be
- used for cleanup as well.
- This will attempt to undo all of the configuration steps done by LCONF,
- including unloading the kernel modules.
-\layout Description
-
---noexec Print, but don't execute, the steps lconf will perform.
- This is useful for debugging a configuration, and when used with --node,
- can be run on any host.
-\layout Description
-
---gdb Causes LCONF to print a message and pause for 5 seconds after creating
- a gdb module script and before doing any lustre configuration.
- (The gdb module script is always created, however.)
-\layout Description
-
---nosetup Only load modules, do not configure devices or services
-\layout Description
-
---nomod Only setup devices and services, do not load modules
-\layout Description
-
---noexec,-n Don't do anything, but print what would happen.
-\layout Description
-
---verbose,-v Be verbose and show actions while going along
-\layout Description
-
--h,--help Print help.
-\layout Description
-
---maxlevel\SpecialChar ~
-<level> [NOT IMPLEMENTED] Perform configuration of devices and
- services up to level given.
-
-\emph on
-level
-\emph default
- can take the values
-\series bold
-net, dev, svc, fs.
-
-\series default
-When used in conjunction with cleanup services are torn down up to a certain
- level.
-\layout Subsection
-
-EXAMPLES
-\layout Standard
-
-On client nodes this is typically invoked as
-\layout LyX-Code
-
-lconf --node client config.xml
-\layout Standard
-
-in order to give clients, regardless of hostname a single configuration.
-\layout Subsection
-
-BUGS
-\layout Standard
-
-None are known.
-\layout Subsection
-
-AUTHOR
-\layout Standard
-
-Cluster File Systems, Inc.
- 2002 - created
-\the_end
+++ /dev/null
-#LyX 1.2 created this file. For more info see http://www.lyx.org/
-\lyxformat 220
-\textclass amsart-plain
-\language english
-\inputencoding auto
-\fontscheme times
-\graphics default
-\paperfontsize default
-\spacing single
-\papersize letterpaper
-\paperpackage a4
-\use_geometry 0
-\use_amsmath 0
-\use_natbib 0
-\use_numerical_citations 0
-\paperorientation portrait
-\secnumdepth 3
-\tocdepth 3
-\paragraph_separation skip
-\defskip medskip
-\quotes_language english
-\quotes_times 2
-\papercolumns 1
-\papersides 1
-\paperpagestyle default
-
-\layout Section
-
-LCTL
-\layout Subsection
-
-NAME
-\layout Standard
-
-lctl - low level Lustre file system configuration utility
-\layout Subsection
-
-SYNOPSIS
-\layout Standard
-
-
-\series bold
-lctl
-\layout Standard
-
-
-\series bold
-lctl\SpecialChar ~
---device\SpecialChar ~
-<devno> <command\SpecialChar ~
-[args]>
-\layout Standard
-
-
-\series bold
-lctl\SpecialChar ~
---threads\SpecialChar ~
-<numthreads>\SpecialChar ~
-<verbose>\SpecialChar ~
-<devno>\SpecialChar ~
-<command [args]>
-\layout Subsection
-
-DESCRIPTION
-\layout Standard
-
-The program can be invoked in interactive mode by issuing
-\series bold
-lctl.
-
-\series default
- After that commands are issued as below.
- The most common commands in lctl are (in matching pairs)
-\family typewriter
-device
-\family default
-,
-\family typewriter
-attach
-\family default
- and
-\family typewriter
-detach
-\family default
-,
-\family typewriter
-setup
-\family default
- and
-\family typewriter
-cleanup
-\family default
-,
-\family typewriter
-connect
-\family default
- and
-\family typewriter
-disconnect
-\family default
-,
-\family typewriter
-help
-\family default
-, and
-\family typewriter
-quit
-\family default
-.
- To get a complete listing of available commands, type
-\family typewriter
-help
-\family default
- at the lctl prompt.
- To get basic help on the meaning and syntax of a command, type
-\family typewriter
-help command
-\family default
-.
- Command completion is activated with the
-\family typewriter
-TAB
-\family default
- key, and command history is available via the up- and down-arrow keys.
-
-\layout Standard
-
-For non-interactive single threaded use, one uses the second invocation
- which runs
-\emph on
-command
-\emph default
- after connecting to the
-\emph on
-device.
-
-\emph default
-
-\layout Description
-
---device The device number to be used for the operation.
- The value of devno is an integer, normally found by calling
-\emph on
-lctl name2dev
-\emph default
-on a device name.
-
-\layout Description
-
---threads How many threads should be forked doing the command specified.
- The numthreads variable is a strictly positivie integer indicating how
- many threads should be started.
- Verbose can take values <XXXX>,
-\emph on
-devno
-\emph default
-is used as above.
-\layout LyX-Code
-
-\layout LyX-Code
-
-\layout Description
-
-network\SpecialChar ~
-config
-\begin_deeper
-\layout Description
-
-network\SpecialChar ~
-<tcp/elans/myrinet> Indicate what kind of network applies for the
- configuration commands that follow
-\layout Description
-
-connect\SpecialChar ~
-[[<hostname>\SpecialChar ~
-<port>]\SpecialChar ~
-|\SpecialChar ~
-<elan\SpecialChar ~
-id>] This will establish a connection to
- a remote network network id given by the hostname/port combination or the
- elan id
-\layout Description
-
-disconnect\SpecialChar ~
-<nid> Disconnect from a remote nid
-\layout Description
-
-mynid\SpecialChar ~
-[nid] Informs the socknal of the local nid.
- It defaults to hostname for tcp networks and is automatically setup for
- elan/myrinet networks
-\layout Description
-
-add_uuid\SpecialChar ~
-<uuid>\SpecialChar ~
-<nid> Associate a given UUID with an
-\emph on
-nid
-\emph default
-
-\layout Description
-
-close_uuid\SpecialChar ~
-<uuid> Disconnect a UUID
-\layout Description
-
-del_uuid\SpecialChar ~
-<uuid> Delete a UUID association
-\layout Description
-
-add_route\SpecialChar ~
-<gateway>\SpecialChar ~
-<target>\SpecialChar ~
-[target] Add an entry to the routing table for
- the given target
-\layout Description
-
-del_route\SpecialChar ~
-<target> Delete an entry for the target from the routing table
-\layout Description
-
-route_list Print the complete routing table
-\layout Description
-
-recv_mem\SpecialChar ~
-[size] Set the socket receive buffer size, if the size is omited
- the default size for the buffer is printed
-\layout Description
-
-send_mem\SpecialChar ~
-[size] Set send buffer size for the socket, if size is omited the
- default size for the buffer is printed
-\layout Description
-
-nagle\SpecialChar ~
-[on/off] Enable/disable nagle, omiting the arguement will cause the
- default value to be printed
-\end_deeper
-\layout Description
-
-device\SpecialChar ~
-selection
-\begin_deeper
-\layout Description
-
-newdev Create a new device
-\layout Description
-
-name2dev This command can be used to determine a device number for the given
- device name.
-\layout Description
-
-device This will select the specified OBD device.
- All other commands depend on the device being set.
-
-\layout Description
-
-device_list Show all the devices
-\end_deeper
-\layout Description
-
-device\SpecialChar ~
-config
-\begin_deeper
-\layout Description
-
-attach\SpecialChar ~
-type\SpecialChar ~
-[name\SpecialChar ~
-[uuid]]
-\shape italic
-Attach
-\shape default
- a type to the current device (which you need to set using the
-\family typewriter
-device
-\family default
- command) and give that device a name and UUID.
- This allows us to identify the device for use later, and also tells us
- what type of device we will have.
-\layout Description
-
-setup\SpecialChar ~
-<args...> Type specific device setup commands.
- For obdfilter a setup command tells the driver which block device it should
- use for storage and what type of filesystem is on that device.
-
-\layout Description
-
-cleanup Cleanup a previously setup device
-\layout Description
-
-detach Remove driver (and name and uuid) from the current device
-\layout Description
-
-lov_setconfig\SpecialChar ~
-lov-uuid\SpecialChar ~
-default-stripe-count\SpecialChar ~
-default-stripe-size\SpecialChar ~
-offset\SpecialChar ~
-pattern\SpecialChar ~
-UUID1\SpecialChar ~
-[U
-UID2...] Write LOV configuration to an MDS device
-\layout Description
-
-lov_getconfig\SpecialChar ~
-lov-uuid Read LOV configuration from an MDS device.
- Returns default-stripe-count, default-stripe-size, offset, pattern, and
- a list of OST UUIDs.
-\end_deeper
-\layout Description
-
-device\SpecialChar ~
-operations
-\begin_deeper
-\layout Description
-
-probe\SpecialChar ~
-[timeout] Build a connection handle to a device.
- This command is used to suspend configuration till the lctl command has
- ensured that the mds and osc services are available.
- This is to avoid mount failures in a reebooting cluster
-\layout Description
-
-close
-\layout Description
-
-getattr\SpecialChar ~
-<objid> Get attributes for an OST object <objid>
-\layout Description
-
-setattr\SpecialChar ~
-<objid>\SpecialChar ~
-<mode> Set mode attribute for OST object <objid>
-\layout Description
-
-create\SpecialChar ~
-[num\SpecialChar ~
-[mode\SpecialChar ~
-[verbose]]] Create the specified number <num> of OST objects
- with the given <mode>
-\layout Description
-
-destroy\SpecialChar ~
-<objid> Destroy an OST object
-\layout Description
-
-test_getattr\SpecialChar ~
-<num>\SpecialChar ~
-[verbose\SpecialChar ~
-[[t]objid]] Do <num> getattrs on OST object <objid>
- (objectid+1 on each thread)
-\layout Description
-
-test_brw\SpecialChar ~
-[t]<num>\SpecialChar ~
-[write\SpecialChar ~
-[verbose\SpecialChar ~
-[npages\SpecialChar ~
-[[t]objid]]]] Do <num> bulk read/writes
- on OST object <objid> (<npages> per I/O)
-\layout Description
-
-test_ldlm Perform lock manager test
-\layout Description
-
-ldlm_regress_start\SpecialChar ~
-%s\SpecialChar ~
-[numthreads\SpecialChar ~
-[refheld\SpecialChar ~
-[numres\SpecialChar ~
-[numext]]]] Start lock manager
- stress test
-\layout Description
-
-ldlm_regress_stop Stop lock manager stress test
-\layout Description
-
-dump_ldlm Dump all lock manager state, this is very useful for debugging
-\layout Description
-
-newconn\SpecialChar ~
-<olduuid>\SpecialChar ~
-[newuuid]
-\end_deeper
-\layout Description
-
-debug
-\begin_deeper
-\layout Description
-
-debug_kernel\SpecialChar ~
-[file]\SpecialChar ~
-[raw] Get debug buffer and dump to a fileusage
-\layout Description
-
-debug_file\SpecialChar ~
-<input>\SpecialChar ~
-[output]\SpecialChar ~
-[raw] Read debug buffer from input and dump to
- outputusage
-\layout Description
-
-clear Clear kernel debug buffer
-\layout Description
-
-mark\SpecialChar ~
-<text> Insert marker text in kernel debug buffer
-\layout Description
-
-filter\SpecialChar ~
-<subsystem\SpecialChar ~
-id/debug\SpecialChar ~
-mask> Filter message type from the kernel debug
- buffer
-\layout Description
-
-show\SpecialChar ~
-<subsystem\SpecialChar ~
-id/debug\SpecialChar ~
-mask> Show specific type of messages
-\layout Description
-
-debug_list\SpecialChar ~
-<subs/types> List all the subsystem and debug types
-\layout Description
-
-panic Force the kernel to panic
-\end_deeper
-\layout Description
-
-control
-\begin_deeper
-\layout Description
-
-help Show a complete list of commands, help <command name> can be used to
- get help on specific command
-\layout Description
-
-exit Close the lctl session
-\layout Description
-
-quit Close the lctl session
-\end_deeper
-\layout Subsection
-
-EXAMPLES
-\layout Description
-
-attach
-\layout LyX-Code
-
-# lctl
-\newline
-lctl > newdev
-\newline
-lctl > attach obdfilter OBDDEV OBDUUID
-\layout Description
-
-connect
-\layout LyX-Code
-
-lctl > name2dev OSCDEV
-\newline
-2
-\newline
-lctl > device 2
-\newline
-lctl > connect
-\newline
-
-\layout Description
-
-getattr
-\layout LyX-Code
-
-lctl > getattr 12
-\newline
-id: 12
-\newline
-grp: 0
-\newline
-atime: 1002663714
-\newline
-mtime: 1002663535
-\newline
-ctime: 1002663535
-\newline
-size: 10
-\newline
-blocks: 8
-\newline
-blksize: 4096
-\newline
-mode: 100644
-\newline
-uid: 0
-\newline
-gid: 0
-\newline
-flags: 0
-\newline
-obdflags: 0
-\newline
-nlink: 1
-\newline
-valid: ffffffff
-\newline
-inline:
-\newline
-obdmd:
-\newline
-lctl > disconnect
-\newline
-Finished (success)
-\layout Description
-
-setup
-\layout LyX-Code
-
-lctl > setup /dev/loop0 extN
-\newline
-lctl > quit
-\layout LyX-Code
-
-\layout Subsection
-
-BUGS
-\layout Standard
-
-None are known.
-\layout Subsection
-
-AUTHOR
-\layout Standard
-
-Cluster File Systems, Inc.
- 2002 - created
-\the_end
+++ /dev/null
-#LyX 1.2 created this file. For more info see http://www.lyx.org/
-\lyxformat 220
-\textclass amsart
-\language english
-\inputencoding auto
-\fontscheme times
-\graphics default
-\paperfontsize default
-\spacing single
-\papersize letterpaper
-\paperpackage a4
-\use_geometry 0
-\use_amsmath 0
-\use_natbib 0
-\use_numerical_citations 0
-\paperorientation portrait
-\secnumdepth 3
-\tocdepth 3
-\paragraph_separation skip
-\defskip medskip
-\quotes_language english
-\quotes_times 2
-\papercolumns 1
-\papersides 1
-\paperpagestyle default
-
-\layout Section
-
-lmc
-\layout Subsection
-
-NAME
-\layout Standard
-
-lmc - lustre configuration maker.
-\layout Subsection
-
-SYNOPSIS
-\layout Standard
-
-
-\series bold
-lmc [options] --add <objectype> [args]
-\layout Standard
-
-
-\series bold
-NOT IMPLEMENTED -- lmc [options] --remove <objecttype> [args]
-\layout Standard
-
-
-\series bold
-NOT IMPLEMENTED -- lmc [options] --convert [args]
-\layout Subsection
-
-DESCRIPTION
-\layout Standard
-
-At present lmc when invoked adds configuration data to the config file.
- lmc will also be able to remove configuration data or convert its forma.
- One generates a single config file for the cluster at present including
- at the minimum mds's, mtpt's and ost's and whatever those reference (e.g.
- net's and profiles)
-\layout Standard
-
-The objecttype refers to a collection of related configuration entities
- and can be one of
-\series bold
-net, mds, lov, ost, mtpt, route, oscref.
-
-\series default
-We describe the arguments required for the addition of each objecttype.
- [NOT implemented] Lmc can also remove items from or convert the format
- of configuration data.
-\layout Standard
-
-to generate configuration data associated with systems in a Lustre cluster.
-
-\layout Description
-
---add\SpecialChar ~
-net Adds a network device descriptor for the given node, with parameters
- as indicated.
-\begin_deeper
-\layout Standard
-
-The arguments required are
-\layout Description
-
---node\SpecialChar ~
-''node_name'' If not present this will create a new node with the
- given name.
- This is also used to specify a specific node for other elements, and the
-\layout Description
-
---nettype\SpecialChar ~
-<type> this can be
-\series bold
-tcp, elan, gm
-\layout Description
-
---nid\SpecialChar ~
-nid the network id, e.g.
- ElanID or IP address as used by portals.
- If host_name is '*', then the local address while be substituted when the
- node is configured with lconf.
-\layout Description
-
---router optional flag to mark this node as a router
-\layout Description
-
---profile optional flag to mark this node as a profile node.
- This is automatically true if the the --nid argument contains a '*'.
-\layout Description
-
---port\SpecialChar ~
-[port] optional argument to indicate the tcp port.
- The default is 988.
-
-\layout Description
-
---tcpbuf\SpecialChar ~
-<size> optional argument
-\end_deeper
-\layout Description
-
---add\SpecialChar ~
-mds
-\begin_deeper
-\layout Description
-
---mds\SpecialChar ~
-<mds_name>
-\layout Description
-
---device\SpecialChar ~
-<pathname>
-\layout Description
-
---size\SpecialChar ~
-<size> optional argument indicating the size of the device to be created
- (used typically for loop devices).
-\layout Description
-
---node\SpecialChar ~
-<nodename> Adds an MDS to the specified node.
- This requires a --node argument, and it must not be a profile node.
-\end_deeper
-\layout Description
-
---add\SpecialChar ~
-lov Creates an LOV with the specified parameters.
- The mds_name must already exist in the descriptor.
-\begin_deeper
-\layout Description
-
---lov_<name>
-\layout Description
-
---mds_<name>
-\layout Description
-
---stripesize\SpecialChar ~
-<size>
-\layout Description
-
---stripecount\SpecialChar ~
-<count>
-\layout Description
-
---pattern\SpecialChar ~
-<pattern> Pattern can be 0.
-\end_deeper
-\layout Description
-
---add\SpecialChar ~
-ost Creates an OBD, OST, and OSC.
- The OST and OBD are created on the specified node.
-\begin_deeper
-\layout Description
-
---ost\SpecialChar ~
-<name> [NOT IMPLEMENTED] Name to give to this OST target.
-\layout Description
-
---node\SpecialChar ~
-<nodename> Node on which the OST service is run, can not be a profile
- node.
-\layout Description
-
---device\SpecialChar ~
-
-\layout Description
-
---size\SpecialChar ~
-[size]
-\layout Description
-
---lov\SpecialChar ~
-<name> Name of LOV to which this OSC will be attached.
-
-\layout Description
-
---obduuid\SpecialChar ~
-UUID specify the UUID of the OBD device.
- The default value is OBD_nodename_UUID.
-\end_deeper
-\layout Description
-
---add\SpecialChar ~
-mtpt Creates a mount point on the specified node.
- Either an LOV or OSC name can be used.
-\begin_deeper
-\layout Description
-
---node\SpecialChar ~
-node node or profile node that will use the mtpt
-\layout Description
-
---path\SpecialChar ~
-/mnt/path\SpecialChar ~
-
-\layout Description
-
---mds\SpecialChar ~
-mds_name
-\layout Description
-
---mdc\SpecialChar ~
-lov_name|osc_name
-\end_deeper
-\layout Description
-
---add\SpecialChar ~
-route Creates a static route through a gateway to a specific nid or
- a range of nids.
-\begin_deeper
-\layout Description
-
---node\SpecialChar ~
-node node or profile node to add the route to
-\layout Description
-
---gw\SpecialChar ~
-nid the nid of the gateway (must be a local interface or a peer)
-\layout Description
-
---tgt\SpecialChar ~
-nid for a specific route, this is the target nid
-\layout Description
-
---lo\SpecialChar ~
-nid for a range route, this is the lo value nid
-\layout Description
-
---hi\SpecialChar ~
-nid for a range route, this is the hi value nid
-\end_deeper
-\layout Description
-
---add\SpecialChar ~
-oscref Adds an OSC reference to a node.
- This is only necessary when the the OSC will be used without a mountpoint.
-\begin_deeper
-\layout Description
-
---node\SpecialChar ~
-node node or profile node to add the OSC ref to
-\layout Description
-
---osc\SpecialChar ~
-osc_name Name of the OSC to add a reference to.
- The --add ost command automatically creates the OSC, and the name will
- be OSC_<node>, where node is the name of node the OST is on.
-\end_deeper
-\layout Description
-
-Options:
-\begin_deeper
-\layout Description
-
---output\SpecialChar ~
-filename Sends output to the file.
- If the file exists, it will be overwritten.
-\layout Description
-
---merge\SpecialChar ~
-filename Add the new element to an existing file.
-
-\end_deeper
-\layout Subsection
-
-EXAMPLES
-\layout Standard
-
-Real life examples are given in the lustre-conf man page.
-\layout Subsection
-
-BUGS
-\layout Standard
-
-None are known.
-\layout Subsection
-
-AUTHOR
-\layout Standard
-
-Cluster File Systems, Inc.
- 2002 - created
-\the_end
+++ /dev/null
-#! /usr/bin/perl
-# postbar - Massage chbar.sh output into valid LaTeX
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Gord Eagle <gord@clusterfs.com>, 2002-08-10
-
-my $progname = $0;
-$progname =~ s|^.*/||;
-my $CHANGE_ENVIRONMENT = '\\\\(begin|end)\\{([^\\}]+)\\}';
-my (@envname, @envdepth, @envbuf);
-my $phony_preamble = 0;
-my $cbdepth = 0;
-my $cbfound = 0;
-
-# Tell whether an environment cannot have arbitrary changebars.
-sub fragile_environment
-{
- my ($env) = @_;
- return $env ne 'document';
-}
-
-
-# Tell whether we can hava arbitrary stuff.
-sub toplevel
-{
- my ($env) = @_;
- return $env eq 'document';
-}
-
-
-sub out
-{
- my (@msg) = @_;
- if ($#envbuf < 0 || toplevel($envname[0])) {
- print @msg;
- } else {
- $envbuf[0] .= join('', @msg);
- }
-}
-
-
-# Leave an environment.
-sub end_environment
-{
- my ($env) = @_;
-
- #out("%$progname end $env\n");
- if ($envname[0] ne $env) {
- die "Expecting \\end{$envname[0]} but got \\end{$env}\n";
- }
-
- if ($cbfound) {
- # Did we find a changebar?
- $cbfound = !toplevel($envname[1]);
- if (!$cbfound) {
- # We found one, and the parent environment is the top level.
- if ($cbdepth == $envdepth[0]) {
- # There was no change in depth, so mark the environment.
- $envbuf[0] = "\\cbstart{}%$progname\n" . $envbuf[0];
- out("\\cbend{}%$progname\n");
- } elsif ($envdepth[0] > $cbdepth) {
- # There were more ends in the environment, so append them.
- for (my $i = 0; $i < $envdepth[0] - $cbdepth; $i ++) {
- out("\\cbend{}%$progname\n");
- }
- } else {
- # There were more starts, so prepend them.
- my $starts;
- for (my $i = 0; $i < $cbdepth - $envdepth[0]; $i ++) {
- $starts .= "\\cbstart{}%$progname\n";
- }
- $envbuf[0] = $starts . $envbuf[0];
- }
- }
- }
-
- # Drop the environment from the list.
- shift(@envname);
- shift(@envdepth);
- out(shift(@envbuf));
-}
-
-
-while ($_ = <STDIN>) {
- chomp;
- my $env;
- if (!/\\begin.*\\end/ && /$CHANGE_ENVIRONMENT/o) {
- $env = $2;
- if ($1 eq 'begin') {
- # Enter the new environment.
- unshift(@envname, $env);
- unshift(@envdepth, $cbdepth);
- unshift(@envbuf, '');
- #out("%$progname depth=$cbdepth, $#envname ($env)\n");
- } elsif (!$phony_preamble) {
- out("$_\n");
- end_environment($env);
- next;
- }
- }
-
- if ($#envname >= 0 && /^\\documentclass/) {
- $phony_preamble = 1;
- }
-
- if ($phony_preamble) {
- # Comment out and ignore the redundant preambles.
- out("%$progname $_\n");
- $phony_preamble = 0 if ($env eq 'document');
- next;
- } elsif ($#envname >= 0) {
- # Track the current changebar depth.
- if (/^\\cbstart/) {
- $cbdepth ++;
- if (!toplevel($envname[0])) {
- $cbfound = 1;
- out("%$progname $_\n");
- next;
- }
- } elsif (/^\\cbend/) {
- if ($cbdepth == 0) {
- die "$progname: Too many \\cbend{}s\n";
- }
- $cbdepth --;
- if (!toplevel($envname[0])) {
- $cbfound = 1;
- out("%$progname $_\n");
- next;
- }
- } elsif (/^\\cbdelete/ && fragile_environment($envname[0])) {
- # What to do with delete bars?
- out("%$progname $_\n");
- next;
- }
- out("$_\n");
- } else {
- out("$_\n");
- # Add the options to the usepackage.
- if (/^\\usepackage.*\{changebar\}$/) {
- # Prevent PostScript dictionary overflow errors.
- out("\\def\\cb\@maxpoint{15}\n");
-
- # Show the bars.
- out("\\outerbarstrue\n");
- }
- }
-
- if (defined($env)) {
- }
-}
-
-exit(0);
+++ /dev/null
-#!/usr/bin/perl -w
-
-# tex2pdf - script for translating latex docs to pdf
-#
-# Copyright (C) 2000-2002 by Steffen Evers and others
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# The GNU General Public License is also available online:
-# http://www.gnu.org/licenses/gpl.html
-#
-# Thanks a lot to all the people that have already contributed to this project!
-#
-# The changelog including the credits has become too long. So, I have removed it
-# from the script, but it is still available online (see below).
-#
-# Special thanks to the following people for their contribution
-# (see the changelog for details):
-# Matej Cepl, Herbert Voss, Nicolas Marsgui, Bruce Foster, Mark van Rossum,
-# Matt Bandy, Garrick Chien Welsh, Stacy J. Prowell, Pavel Sedivy,
-# Holger Daszler, Olaf Gabler, Ahmet Sekercioglui, Richard, Steffen Macke,
-# Rainer Dorsch & friends, Jean-Pierre Chretien, Fernando Perez,
-# Ha Duong Minh, Oscar Lopez
-#
-# Project Homepage: http://tex2pdf.berlios.de
-# Developer Homepage: http://developer.berlios.de/projects/tex2pdf
-# Mailing lists: http://developer.berlios.de/mail/?group_id=57
-# Changelog: http://tex2pdf.berlios.de/changelog.html
-#
-# Anyone is invited to help to improve tex2pdf. Therefore any kind of feedback
-# is welcome. Maybe you even would like to hack the code and send us your
-# changes. This would help a lot and is highly appreciated. Think about it :-)
-# Subscribing to the developer mailing list might be a first step (see above).
-#
-# Send feedback to: tex2pdf-devel@lists.berlios.de
-#
-
-######## Imports
-
-use File::Basename;
-use File::Copy;
-use Getopt::Long;
-use Sys::Hostname;
-use Cwd;
-use strict;
-
-####### global variables
-
-my $MYRELEASE="3.0.21";
-my $MYHOSTNAME=hostname;
-my $MYNAME=basename $0;
-my $MYUSER=$ENV{'USER'};
-my $USER_HOME=$ENV{'HOME'};
-if (not $MYUSER) { $MYUSER = 'nobody'; }
-if (not $USER_HOME) { $USER_HOME = '/tmp'; }
-
-my @TMPFILES=();
-my @TMP_TEX_FILES=();
-my $NUM_PARAM_MIN=0;
-my $NUM_PARAM_MAX=9;
-my @REF_DOCS;
-my $MTP_PREAMBLE_FILENAME="preamble.cfg";
-my $MTP_TMP_BASESUFFIX="-mp";
-my @EPS_SUFFIXES=('eps','ps','ps.gz','eps.gz' );
-my $PDF_ORIG_SUFFIX='pdf.orig';
-my @BITMAP_SUFFIXES=( 'jpg', 'png', 'tif' );
-
-# (initial) log file of this script
-# this log file will be moved to the specified log_dir after configuration
-# and the variable will be updated to the new name
-my $MYLOGFILE="$USER_HOME/tex2pdf-$$.log";
-my $LOGFILE_VERBOSITY=9;
-
-### text token for no value
-my $NIL="NOVALUE";
-my $UNDEF="undefined";
-
-### token for boolean 'false', 'no'
-my $NO="no";
-my $FALSE=0;
-
-### token for boolean 'true', 'yes'
-my $YES="yes";
-my $TRUE=1;
-
-### file to store private parameters
-# If you only want to change your private parameters change them there
-# default: $HOME/.tex2pdf3rc
-my $RC_FILENAME="$USER_HOME/.tex2pdf3rc";
-my $MYRCFILE_VERSION=7;
-my $RCVERSION_STRING="rcfile_version";
-
-## set global variable configured to prevent access to configuration
-# parameters before configuration process is finished
-my $CONFIGURED=$FALSE;
-my $PRE_CONFIG_VERBOSITY=4;
-
-########################## NEW PERL CONFIGURATON
-
-my %CONFIGURATION = ();
-my %PARAMETER_LIST = ();
-my @PARAMETER_ORDER = ();
-my %PARAMETER_TYPES = ();
-
-## Array index for the various information in each parameter specifcation
-## referenced by %PARAMETER_LIST
-my $TYPE=0;
-my $OPT_ALIAS=1;
-my $OPT_SPEC=2;
-my $DEF_VALUE=3;
-my $DESCRIPTION=4;
-my $QUESTION=5;
-my $EXPLANATION=6;
-
-&add_param_type('paper',
- [ ['a4paper' , 'a4 paper' ],
- [ 'letterpaper', 'letter paper' ],
- [ 'legalpaper', 'legal paper' ],
- [ 'executivepaper', 'executive paper' ],
- [ $NIL, 'do not set value - leave it to hyperref' ]
- ] );
-
-&add_param_type('color',
- [ [ 'yellow', 'LaTeX color yellow' ],
- [ 'red', 'LaTeX color red' ],
- [ 'green', 'LaTeX color green' ],
- [ 'cyan', 'LaTeX color cyan' ],
- [ 'blue', 'LaTeX color blue' ],
- [ 'magenta', 'LaTeX color magenta' ],
- [ 'black', 'LaTeX color black' ],
- [ $NIL , 'do not set this value - leave it to hyperref' ]
- ] );
-
-&add_param_type('destination',
- [ [ 'source', 'directory of the LaTeX source document' ] ,
- [ 'input', 'root directory of referenced material' ],
- [ 'custom', 'custom directory as specified' ]
- ] );
-
-### Option parameters: these parameters have no default value and can not
-# be configured interactively, but only as a command line option
-# an option parameter is not allowed to have a default value, question or
-# explanation
-# and all parameter of type action are treated as option parameters
-# $key, $type, $def_value, $opt_alias, $opt_spec, $description, $question, $explanation
-
-&add_param('help', 'action', undef, '|h', '',
- 'print a short help text and exit');
-
-&add_param('version', 'action', undef, '|v', '',
- 'print the version of this script and exit');
-
-&add_param('print_config', 'action', undef, '|o', '',
- 'print the current configuration and exit');
-
-&add_param('configure', 'action', undef, '|c', '',
- 'configure all parameters interactivly, store them and exit');
-
-&add_param('title', 'text', undef, '|t', '=s',
- 'set PDF info title for specified document');
-
-&add_param('author', 'text', undef, '|a', '=s',
- 'set PDF info author for specified document');
-
-&add_param('input_path', 'directory', undef, '', '=s',
- 'set path for referenced material in main document');
-
-### Full parameters
-# parameter type action is not allowed
-# $key, $type, $def_value, $opt_alias, $opt_spec, $description, $question, $explanation
-
-&add_param('logdir', 'directory',"$USER_HOME/tex2pdf-log/", '', '=s',
- 'set directory for saving log files',
- 'What log directory should be used?',
- "The log directory is used to store information about the generation\n"
- ."process for later review, e.g. for debugging.");
-
-&add_param('lyxrc_path', 'directory', "$USER_HOME/.lyx/", '', '=s',
- 'set the configuration directory of LyX',
- 'What is the directory for your LyX configuration data?',
- "If I have to generate a LateX file from a LyX file I need to clear two "
- ."temporary\nfiles in your LyX configuration directory. They will "
- ."be backuped and normally\ndo not contain any valuable data anyway. If "
- ."you do not use LyX, simply leave\nthe default.");
-
-&add_param('lyx_exec', 'text', "lyx", '', '=s',
- 'specify the LyX executable for converting lyx to latex',
- 'Which executable should I use for converting LyX docs to LaTeX?',
- "I use LyX to generate a LateX file from a LyX file. As you might use\n"
- ."several versions of LyX at the same time or do not have it in your path"
- ."\nyou can give me the apropriate executable here (e.g. '/usr/bin/lyx')."
- ."\nIn most cases the default 'lyx' should be fine.");
-
-&add_param('debug', 'bool', $NO, '', '!',
-'do not delete temporary files after execution and be as verbose as possible',
- 'Do you want to debug this script?',
- "I will not remove any temporary files. This could cause problems on a "
- ."second\nexecution as I might refuse to overwrite these files for security "
- ."reasons.\nYou have to remove them manually in this case. Additionally, I "
- ."will provide\nas much information during execution as possible.");
-
-&add_param('delete_pdf_images', 'bool', $NO, '', '!',
- 'delete generated PDF image files after execution',
- 'Should generated PDF image files be deleted after execution?',
- "Pdflatex cannot handle EPS images. Therefore all such images need to be\n"
- ."translated to PDF in advance. After a successful generation of the final "
- ."PDF \ndocument or after encountering an error I could leave this PDF "
- ."images for\n later executions or simply delete them.");
-
-&add_param('clean_on_abort', 'bool', $YES, '', '!',
- 'also delete temporary files after abort',
- 'Should temporary files be deleted when aborting?',
- "When the generation of the PDF file fails for some reason you might still "
- ."want\nto keep already generated temporary files for some reason, e.g. "
- ."debugging.\nIf you do not want to keep them set this parameter to 'yes'.");
-
-&add_param('tmp_base_suffix', 'text', '-pdf', '', '=s',
- 'specify the extension of the basename for temporary TeX files',
- 'What string should be used as basename suffix for temporary files?',
- "I have to find names for my temporary files. Therefore I construct a new "
- ."name\nfrom the original filename and this string. Me and various called "
- ."applications\nwill then create several files with this constructed "
- ."basename and different\nextensions. When cleaning up I will simple "
- ."delete all files with the\nconstructed basenames I have used.");
-
-&add_param('overwrite', 'bool', $NO, '', '!',
- 'ignore existence of files with same basename as temporary TeX files',
- 'Should I overwrite existing (temporary) files?',
- "In spite of the precaution with the appended base suffix, there still "
- ."might\nexist files with an identical basename. If you set this option I "
- ."will consider\nsuch files as old temporary files and overwrite them "
- ."during generation.\nHowever, I will not remove any files with this "
- ."constructed basename on the\nclean up. You have to remove them manually.");
-
-&add_param('clean_logs', 'bool', $YES, '|l', '!',
- 'delete all log files in log directory before execution',
- 'Should the old log files be removed before execution?',
- "I can remove old log files prior to execution. However, you might "
- ."experience\nproblems if you run the script on several documents at the "
- ."same time. If you\nwant to be on the safe side, answer '$NO'. Than you "
- ."have to remove the logs\nmanually from time to time.");
-
-&add_param('check_commands', 'bool', $YES, '', '!',
- 'make sure that required shell commands does exist before start',
- 'Should I look for required executables?',
- "As I use several different applications for PDF generation you might want "
- ."to \nmake sure that they are available before the real work starts.");
-
-&add_param('destination', 'destination', 'source', '', '=s',
- 'specifiy final location of generated PDF document',
- 'Where should I store the resulting PDF document?',
- "Depending on the application that starts this script (or you if you call "
- ."it\ndirectly) you might want to have the resulting PDF document located "
- ."at\ndifferent places.");
-
-&add_param('custom_path', 'directory', $USER_HOME.'/', '|d', '=s',
- "specify custom path for 'destination' parameter",
- 'What custom directory should be used?',
- "When ever you specifiy to store the generated PDF document (command line "
- ."or\nconfiguration) in a custom directory I will put it here.");
-
-&add_param('colorlinks', 'three', $YES, '', '!',
- 'activate colored links in PDF doc (hyperref)',
- 'Should colors be used for links?',
- "I can use different colors for links inside the PDF document.\nYou can "
- ."use '$UNDEF' to tell me that you would like to leave this up to\n"
- ."independent hyperref configuration.");
-
-&add_param('paper', 'paper', 'a4paper', '|p', '=s',
- 'specify papersize of the PDF doc (hyperref)',
- 'What papersize should be used?',
- "I can set the papersize of the resulting PDF document");
-
-&add_param('citecolor', 'color', 'blue', '', '=s',
- 'specify color of citations in PDF doc (hyperref)',
- 'What color should be used for citation?', "");
-
-&add_param('urlcolor', 'color', 'blue', '', '=s',
- 'specify color of URLs in PDF doc (hyperref)',
- 'What color should be used for URLs?', "");
-
-&add_param('linkcolor', 'color', 'blue', '', '=s',
- 'specify color of internal links in PDF doc (hyperref)',
- 'What color should be used for normal internal links?', "");
-
-&add_param('pagecolor', 'color', 'blue', '', '=s',
- 'specify color of links to other pages in PDF doc (hyperref)',
- 'What color should be used for page links?', "");
-
-&add_param('link_toc_page', 'bool', $YES, '', '!',
- 'link table of contents to pages instead of sections (hyperref)',
- 'Should TOC be linked to pages?',
- "The table of contents of the resulting PDF document is normally linked to "
- ."the\ncorresponding section. However, you can also link it to the "
- ."corresponding page\ninstead.");
-
-&add_param('default_title', 'text', $NIL, '', '=s',
- 'set default PDF info title',
- 'What is the default title?',
- "A PDF document contains meta data about itself: the document info.\nOne "
- ."of the info fields is the document title. You can set a default value\n"
- ."which will be used in the case the script cannot determine a proper "
- ."title from\nthe LaTeX document and you have not set one on the command "
- ."line.\nYou can use '$NIL' to tell me that you would like to leave this "
- ."up to\nindependent hyperref configuration.");
-
-&add_param('default_author', 'text', $NIL, '', '=s',
- 'set default PDF info author',
- 'What is the default author?',
- "A PDF document contains meta data about itself: the document info.\nOne "
- ."of the info fields is the document author. You can set a default value\n"
- ."which will be used in the case the script cannot determine a proper "
- ."author\nfrom the LaTeX document and you have not set one on the command "
- ."line.\nYou can use '$NIL' to tell me that you would like to leave this "
- ."up to\nindependent hyperref configuration.");
-
-&add_param('force_index', 'bool', $NO, '|i', '!',
- 'force explicit inclusion of (existing) index in PDF doc',
- 'Should the call of makeindex be forced?',
- "Older versions of pdflatex have not included the index of a document\n"
- ."automatically. If you are missing the index in your document you can "
- ."force the\ncall of makeindex on the condition that an index file was "
- ."generated.");
-
-&add_param('makeindex_opts', 'text', '', '', '=s',
- 'specify extra options for shell execution of makeindex',
- 'What additional options for makeindex should be used?',
- "Sometimes, people would like to pass some extra options over to makeindex. "
- ."This\nis the right place to do that. Everyone else can leave this empty.");
-
-&add_param('bibtex', 'three', $NIL, '|b', '!',
- 'set bibtex behavior',
- 'How should bibtex be used?',
- "The bibtex usage can be specified.\nPossible values are: '$YES' (always "
- ."run bibtex), '$NO' (never run bibtex)\nand '$UNDEF' (scan tex file for "
- ."a bibtex entry and run it if required).");
-
-&add_param('gloss', 'three', $NIL, '', '!',
- 'set gloss behavior',
- 'How should gloss be used?',
- "The gloss usage can be specified.\nPossible values are: '$YES' (always "
- ."run bibtex on file.gls), '$NO' (never run bibtex on file.gls)\nand '$UNDEF' (scan tex file for "
- ."a gloss entry and run it if required).");
-
-&add_param('thumbpdf', 'bool', $NO, '|n', '!',
- 'generate thumbnails for PDF document',
- 'Should PNG thumbnails be created?',
- "I can use thumbpdf to include thumbnails of the document pages in the PDF "
- ."file.\nThis requires Ghostscript 5.50 or higher.");
-
-&add_param('ppower', 'bool', $NO, '|w', '!',
- 'postprocess PDF document with ppower',
- 'Should ppower postprocess the PDF document?',
- "I can use ppower to postprocess the PDF "
- ."file.\nThis requires ppower 4.0 or higher.");
-
-&add_param('authorindex', 'bool', $NO, '', '!',
- 'generate author index for PDF document',
- 'Should authorindex process the PDF document?',
- "I can use authorindex to process to include an author index in the PDF "
- ."file.\nThis requires authorindex.");
-
-
-&add_param('mtp_preamble', 'bool', $NO, '|r', '!',
- "add the file $MTP_PREAMBLE_FILENAME at the current dir to metapost files",
- "Should the $MTP_PREAMBLE_FILENAME file be added to the metapost files?",
- "I can add $MTP_PREAMBLE_FILENAME to metapost "
- ."files.\nThis requires an existing $MTP_PREAMBLE_FILENAME file.");
-
-&add_param('maxrun', 'integer', 6, '', '=i',
- 'specify maximal number of pdflatex runs if problems are detected',
- 'What should be the maximum number of runs for pdflatex (1-6)?', "");
-
-&add_param('minrun', 'integer', 2, '', '=i',
- 'specify minimal number of pdflatex runs if no problems are detected',
- 'What should be the minimum number of runs for pdflatex (1-6)?', "");
-
-&add_param('verbosity', 'integer', 5, '', '=i',
- 'set the level of verbosity',
- 'Which level of verbosity do you want (0-9)',
- "Different people want different amounts of information about what the "
- ."script\nactually does. Therefore you can adjust the verbosity to your "
- ."personal needs\nby setting this parameter to a value from 0 to 9. 0 "
- ."means no output at all\nand 9 means maximal output.");
-
-&add_param('pdftex_opts', 'text', '', '', '=s',
- 'specify extra options for shell execution of pdflatex',
- 'What additional options for pdflatex should be used?',
- "Sometimes, people would like to pass some extra options over to pdflatex. "
- ."This\nis the right place to do that. Everyone else can leave this empty.");
-
-&add_param('hyperref_args', 'text', '', '', '=s',
- 'specify extra arguments for the hyperref package',
- 'What additional arguments should be passed to the hyperref package?',
- "Sometimes, people would like to pass some extra options over to hyperref. "
- ."This\nis the right place to do that. Everyone else can leave this empty.");
-
-# the following parameter types should be set now:
-# 'color' => \@VALUES,
-# 'destination' => \@VALUES,
-# 'paper' => \@VALUES,
-# 'action' => undef,
-# 'three' => undef,
-# 'bool' => undef,
-# 'integer' => undef,
-# 'text' => undef,
-# 'directory' => undef
-
-##### Functions ###########################################
-
-### handle a status report with a given priority level
-# write it to the log file if log file if configuration is done
-# write it to stdout if verbosity is set lower or equal
-#
-# The following priority levels exist:
-# 1: minimal fatal error messages
-# 2: additional information about fatal error
-# 3: non-fatal error message
-# 4: warning
-# 5: major step of the process
-# 6: minor step of the process
-# 7: progress report of minor step
-# 8: long status report from called applications
-# 9: debug info
-#
-# parameter 1: priority level
-# parameter 2: list of output strings
-# return value: none
-
-sub report {
- my $level;
- my $verbosity;
- my $log_verbosity;
- my @output;
-
- if (@_ < 2 ) {
- @output = ( "Oppss! Report function got only 1 argument!" );
- $level = 9;
- } else {
- ($level, @output) = @_;
- }
-
- if($CONFIGURED) {
- if( ¶m_value('debug') eq $NO ) {
- $verbosity = ¶m_value('verbosity');
- $log_verbosity = $LOGFILE_VERBOSITY;
- } else {
- $verbosity = 9;
- $log_verbosity = 9;
- }
- } else {
- $verbosity = $PRE_CONFIG_VERBOSITY;
- $log_verbosity = $LOGFILE_VERBOSITY;
- }
-
- if ( $level <= $log_verbosity ) {
- open LOGFILE, ">> $MYLOGFILE";
- print LOGFILE @output,"\n";
- close LOGFILE;
- }
-
- if( $level <= $verbosity ) {
- print @output,"\n";
- }
-}
-
-### process system command and do the appropriate reports
-# parameter 1: the system command to process
-# parameter 2: flag - TRUE: abort on failure, FALSE: continue on failures
-# parameter 3: priority level for output of system command
-# parameter 4: specific failure message
-# return value: TRUE - success, FALSE - failure
-
-sub system_command {
- my $command = $_[0];
- my $fatal_failure= $_[1];
- my $output_priority = $_[2];
- my $fail_message = $_[3];
- my $system_out;
-
- $system_out = `$command 2>&1`;
-
- if ($?) {
- if ($fatal_failure) {
- &report(2, $system_out) if ($system_out);
- &abort($fail_message.": $!");
- } else {
- &report($output_priority, $system_out) if ($system_out);
- &report(3, $fail_message.": $!");
- }
- return $FALSE;
- }
-
- return $TRUE;
-}
-
-### Index of the first occurence of a string in an array
-# parameter 1: text
-# parameter 2: list
-# return value: index or -1 if not element of the array
-
-sub array_index {
- my ($text, @list) = @_;
-
- if(!defined($text)) {
- &report(9, "Oppss! Cannot compare nothing.");
- return -1;
- }
-
- foreach (0..$#list) {
- if ( $list[$_] eq $text ) { return $_; }
- }
-
- return -1;
-}
-
-### extract the last N lines of a text file
-# abort on failures
-# parameter 1: file to read
-# parameter 2: N - number of lines to print (undef/0: all lines)
-# return value: last N lines
-
-sub file_tail {
- my $file_name = $_[0];
- my $no_of_lines = defined($_[1]) ? $_[1] : 0;
- my @cache=();
-
- &check_file($file_name);
- open(TAIL_SOURCE, "<$file_name")
- or &abort("Could not read file $file_name: $!");
-
- if($no_of_lines == 0) {
- # use entire file
- while(<TAIL_SOURCE>) {
- if(!$_) { $_="\n"; }
- push(@cache, $_);
- }
- } else {
- # only last N lines
-
- # fill up cache
- while(@cache < $no_of_lines and <TAIL_SOURCE>) {
- if(!$_) { $_="\n"; }
- push(@cache, $_);
- }
-
- # always cache the last N lines up to the end of the file
- while(<TAIL_SOURCE>) {
- if(!$_) { $_="\n"; }
- shift(@cache);
- push(@cache, $_);
- }
- }
-
- close TAIL_SOURCE;
-
- return @cache;
-}
-
-### return all lines of FILE which match match regexp EXPR
-# parameter 1: FILE - file to read
-# parameter 2: EXPR - regular expression to match
-# parameter 3: true: exit on first occurence, otherwise get all (default: false)
-# return value: array of matching lines
-
-sub grep_file {
- my $file_name = $_[0];
- my $regexp = $_[1];
- my $first_only = $_[2] ? $TRUE : $FALSE;
- my @result=();
-
- ### open file and abort if not possible
- &check_file($file_name);
- open(GREP_SOURCE, "<$file_name")
- or &abort("Could not read file $file_name: $!");
-
- while(<GREP_SOURCE>) {
- if(m#$regexp#) {
- push(@result, $_);
- if($first_only) { last; }
- }
- }
-
- close GREP_SOURCE;
- return @result;
-}
-
-### Removing all temporary files
-
-sub clean_up {
- &report(6, "Removing temporary files ...");
- foreach (@TMPFILES) {
- unlink($_) if(-f $_);
- }
-
- foreach (@TMP_TEX_FILES) {
- # make sure that we have a good tex file name in order
- # to avoid unintended removals
- if( $_ ne "" and -f $_.'.tex' ) {
- unlink glob($_.".???");
- } else {
- &report(3, "Bad file in temp tex files list: $_");
- }
- }
-}
-
-### Output of all temp files
-
-sub print_temp_files {
- if (scalar @TMPFILES > 0) {
- print "Stored the following explicit temporary files:\n";
- foreach (@TMPFILES) {
- if (-f $_) {
- print "> ".$_."\n";
- } else {
- print "> ".$_." (does not exist)\n";
- }
- }
- print "\n";
- }
-
- if (scalar @TMP_TEX_FILES > 0) {
- print "Stored the following temporary TeX base names:\n";
- foreach (@TMP_TEX_FILES) {
- if( $_ ne "" and -f $_.'.tex' ) {
- print "> ".$_.": ";
- foreach my $file (glob($_.".???")) {
- print basename($file)." ";
- }
- print "\n";
- } else {
- print "> ".$_.": bad file for temp TeX file\n";
- }
- }
- print "\n";
- }
-}
-
-### exit with an error message
-
-sub abort {
- &report(1, @_);
- if ( $CONFIGURED and ¶m_value('clean_on_abort') eq $YES
- and ¶m_value('debug') eq $NO) {
- &clean_up;
- } else {
- &print_temp_files;
- }
- &report(2, "Aborting ...");
- exit 1;
-}
-
-### Check for required command with 'which'; abort if not found
-# parameter $1: command to check
-# parameter $2: remark if specified command is not found
-
-sub checkCommand {
- my $command = $_[0];
- my $message = $_[1];
- my $which_output;
-
- $which_output = `which $command 2>&1`;
- chomp $which_output;
- $_ = $which_output;
- s|^(.*/)?([^/]+)$|$2|;
-
- if ( $_ ne $command ) {
- &report(2, "\n$which_output");
- &report(1, "\nRequired command '$command' seems not to be in your path.");
- if ( defined($message) ) {
- &report(2, "$message");
- }
- &report(2, "Aborting ...");
- exit 1;
- }
-}
-
-###################### Generic configuration functions
-
-### interactively answer a question with yes or no
-# parameter 1: question
-# parameter 2: default value (not set means $NIL)
-# parameter 3: yes: allow undefined as third value
-# no : only yes/no allowed (default)
-# return value: the given answer
-
-sub question_ynu {
- my $user_input;
- my $question = $_[0];
- my $default = defined($_[1]) ? $_[1] : $NIL;
- my $undef_allowed = $_[2];
- my $response = undef;
-
- if (defined($undef_allowed) and $undef_allowed eq $YES) {
- $undef_allowed = $TRUE;
- } else {
- $undef_allowed = $FALSE;
- }
-
- if( $default =~ /^y(es)?/i ) {
- $question .= ' [y]: ';
- $default = $YES;
- } elsif ( $default eq $NIL and $undef_allowed ) {
- $question .= ' [u]: ';
- $default = $NIL;
- } else {
- $question .= ' [n]: ';
- $default = $NO;
- }
- while (! defined($response)) {
- print $question;
- $user_input = <STDIN>;
- chomp($user_input);
-
- if( $user_input =~ /^y(es)?/i ) {
- $response=$YES;
- } elsif ( $user_input =~ /^no?/i ) {
- $response=$NO;
- } elsif ( $user_input =~ /^u(ndef(ined)?)?/i and $undef_allowed ) {
- $response=$NIL;
- } elsif ( $user_input eq "" ) {
- $response=$default;
- } else {
- print "Please respond with y(es)";
- print ", u(ndefined)" if($undef_allowed);
- print " or n(o).\n";
- }
- }
- return $response;
-}
-
-### interactively input a positive integer number
-# parameter 1: question
-# parameter 2: default value
-# parameter 3: min value
-# parameter 4: max value
-# return value: the input number
-
-sub input_number {
- my $question = $_[0];
- my $default = $_[1];
- my $min_limit = $_[2];
- my $max_limit = $_[3];
- my $response= undef;
-
- while (! defined($response)) {
- print "$question [$default]: ";
- my $user_input = <STDIN>;
- chomp($user_input);
-
- if ($user_input eq "") {
- $response=$default;
- } else {
- $_ = $user_input;
- if (s/^([0-9]+)$/$1/ and $_ >= $min_limit and $_ <= $max_limit ) {
- $response = $_;
- } else {
- print "Invalid input. Please enter a positve integer from $min_limit to $max_limit.\n";
- }
- }
- }
- return $response;
-}
-
-### interactively choose between several given values
-# parameter 1: question
-# parameter 2: default value
-# parameter 3: reference to an array of possible values arrays
-# return value: the chosen value
-
-sub choose_value {
- my ($question, $default, $enum_array_ref)=@_;
- my $default_no=1;
- my $chosen_no;
- my @possible_values = @$enum_array_ref;
- my @value_array;
- my $value_key;
- my $value_output;
-
- print "$question\n";
- foreach (0..$#possible_values) {
- my $no = $_ + 1;
- @value_array = @{$possible_values[$_]};
- $value_key = $value_array[0];
- $value_output = $value_array[1];
-
- print "$no) " . $value_output . "\n";
- if ( $default eq $value_key ) { $default_no=$no; }
- }
-
- $chosen_no=&input_number("Please enter the corresponding number", $default_no, 1, $#possible_values);
-
- @value_array = @{$possible_values[$chosen_no - 1]};
- $value_key = $value_array[0];
- return $value_key;
-}
-
-### interactively answer a question
-# parameter 1: question
-# parameter 2: current value
-# return value: the new value
-
-sub input_text {
- my $question=$_[0];
- my $default=$_[1];
- my $response= undef;
-
- print "Suggested value: $default\n";
- if ( &question_ynu("Do you want to keep this value?", $YES) eq $YES ) {
- $response= $default;
- } else {
- print "$question ";
- my $user_input = <STDIN>;
- chomp($user_input);
-
- $response = $user_input;
- }
- return $response;
-}
-
-##### Make sure that specified file exists and is readable; abort if missing
-# parameter 1: file to check
-# parameter 2: remark if check fails on specified file
-
-sub check_file {
- my $file = $_[0];
- my $message = defined($_[1]) ? $_[1] : "Required file cannot be accessed!";
-
- if ( ! -f $file ) {
- &report(2, "\nSorry. I cannot find '$file'.");
- &abort($message);
- } elsif ( ! -r $file ) {
- &report(2, "\nSorry. File '$file' exists, but is not readable.");
- &abort($message);
- }
-}
-
-##### Make sure that specified directory exists and is writable
-# parameter 1: directory to check
-# parameter 2: remark if check fails on specified directory
-# parameter 3: if yes, creation is allowed
-# return value: $TRUE - ok; $FALSE - error
-
-sub check_dir {
- my $directory = $_[0];
- my $message = defined($_[1]) ? $_[1] : "Not a valid path!";
- my $allow_creation = defined($_[2]) ? $_[2] : $NO;
-
- if ( index($directory, "/") != 0 ) {
- &report(3, "\nSorry. '$directory' is not an absolute path.");
- &report(3, $message);
- return $FALSE;
- } elsif ( ! -d $directory ) {
- # dir does not exist
- if ( $allow_creation eq $YES ) {
- # creation allowed
- &report(4, "\nI cannot find '$directory'. Try to create it.");
- if ( mkdir($directory, 0755) ) {
- &report(7, "Creation of '$directory' was successful.");
- return $TRUE;
- } else {
- &report(3, "Creation of '$directory' failed.");
- &report(3, $message);
- return $FALSE;
- }
- } else {
- # creation not allowed
- &report(3, "\nSorry. Directory '$directory' does not exist.");
- &report(3, $message);
- return $FALSE;
- }
- } elsif ( ! -w $directory ) {
- # dir not writable
- &report(3, "\nSorry. Directory '$directory' exists, but is not writable.");
- &report(3, $message);
- return $FALSE;
- }
- return $TRUE;
-}
-
-### interactively input a directory for data storage (absolute path)
-# parameter 1: question
-# parameter 2: default dir
-# parameter 3: if 'yes' allow creation of directory
-# return value: the specified directory
-
-sub input_dir {
- my $question = $_[0];
- my $default_dir = $_[1];
- my $allow_creation = defined($_[2]) ? $_[2] : $NO;
- my $user_input;
- my $response = undef;
-
- if ( defined($default_dir) and index($default_dir, "/") == 0
- and ( (! -d $default_dir and $allow_creation eq $YES)
- or (-d $default_dir and -w $default_dir) ) ) {
- $question .= " [$default_dir]: ";
- } else {
- $default_dir = undef;
- $question .= ": ";
- }
-
- while (! defined($response)) {
- print "$question";
- $user_input = <STDIN>;
- chomp($user_input);
-
- if( $user_input eq "" and defined($default_dir) ) {
- # user has only pressed <ENTER> and thereby confirmed default value
- if( ! &check_dir($default_dir,"Default value was not valid. Please, give different directory.", $allow_creation ) ) {
- # default dir does not exist and cannot be created
- $default_dir = undef;
- $question = "$_[0]: ";
- } else {
- # valid default dir has already existed or has been created
- $response = $default_dir;
- }
- } else {
- # user has given a directory
- if( &check_dir($user_input,"This is not a valid directory!", $allow_creation) ) {
- $response = $user_input;
- }
- }
- }
- return $response;
-}
-
-#### add a new parameter type with corresponding additional data argument
-#### parameters types
-# parameter 1: type key
-# parameter 2: additonal data for the type
-# e.g. for enum type: reference to list of arrays
-# return value: none
-
-sub add_param_type {
-
- my ($type, $scalar_argument) = @_;
-
- $PARAMETER_TYPES{$type} = $scalar_argument;
-}
-
-#### add a new parameter to the adminstrated parameters
-####
-# parameter 1: key
-# parameter 2: type
-# parameter 3: default value
-# parameter 4: alias for command line options
-# parameter 5: specification for command line options
-# parameter 6: short description for help
-# parameter 7: question
-# parameter 8: explanation
-# return value: none
-
-sub add_param {
-
- my ($key, $type, $def_value, $opt_alias, $opt_spec, $description, $question, $explanation) = @_;
-
- $CONFIGURATION{$key} = $def_value;
-
- $PARAMETER_LIST{$key} = [ $type, $opt_alias, $opt_spec, $def_value, $description, $question, $explanation ];
-
- push(@PARAMETER_ORDER, $key);
-
- if (! exists $PARAMETER_TYPES{$type}) {
- $PARAMETER_TYPES{$type} = undef;
- }
-}
-
-### get the value of an existing parameter
-# parameter 1: a parameter key
-# return value: reference to the array of possible value entries
-# (undef if not valid)
-
-sub type_enum_array {
- my $key = $_[0];
- my $values_ref;
-
- if(! exists($PARAMETER_TYPES{$key})) {
- &abort("unknown type: $key");
- }
-
- $values_ref = $PARAMETER_TYPES{$key};
-
- if(ref $values_ref ne 'ARRAY') {
- $values_ref = undef;
- }
-
- return $values_ref;
-}
-
-### get the value of an existing parameter
-# parameter 1: a parameter key
-# return value: parameter value
-
-sub param_value {
- my $key = $_[0];
- my $current_value;
-
- exists($CONFIGURATION{$key})
- or &abort("unknown parameter: $key");
- $current_value = $CONFIGURATION{$key};
-
- return $current_value;
-}
-
-### get the type of an existing parameter
-# parameter 1: a parameter key
-# return value: parameter value
-
-sub param_type {
- my $key = $_[0];
- my $def_ref;
- my $type;
-
- exists($PARAMETER_LIST{$key})
- or &abort("unknown parameter: $key");
- $def_ref = $PARAMETER_LIST{$key};
- $type = @{$def_ref}[$TYPE];
-
- exists($PARAMETER_TYPES{$type})
- or &abort("parameter has unknown type: $key (type: $type)");
-
- return $type;
-}
-
-### determine if the given parameter is a full one (instead of option only)
-# parameter 1: a parameter key
-# return value: $TRUE - full parameter; $FALSE otherwise
-
-sub full_param {
- my $key = $_[0];
- my @param_def;
-
- exists($PARAMETER_LIST{$key})
- or &abort("unknown parameter: $key");
- @param_def = @{$PARAMETER_LIST{$key}};
-
- if ($param_def[$TYPE] ne 'action' and defined ($param_def[$QUESTION])) {
- return $TRUE;
- } else {
- return $FALSE;
- }
-}
-
-### get the output needed for configuration of this parameter
-# parameter 1: a parameter key
-# return value: array - (description, explanation, question)
-
-sub param_config_output {
- my $key = $_[0];
- my @param_def;
- my $description;
- my $explanation;
- my $question;
-
- exists($PARAMETER_LIST{$key})
- or &abort("unknown parameter: $key");
- @param_def = @{$PARAMETER_LIST{$key}};
- $description = $param_def[$DESCRIPTION];
- $explanation = $param_def[$EXPLANATION];
- $question = $param_def[$QUESTION];
-
- return ($description, $explanation, $question);
-}
-
-### set the value of an existing parameter
-# parameter 1: a parameter key
-# parameter 2: the new value
-# return value: none
-
-sub set_param_value {
- my $key = $_[0];
- my $new_value = $_[1];
-
- exists($CONFIGURATION{$key})
- or &abort("unknown parameter: $key");
- $CONFIGURATION{$key}=$new_value;
-}
-
-### get option specifier for getopts
-# parameter 1: option key
-# return value: string - option specifier
-
-sub option_specifier {
- my $key = $_[0];
- my $spec;
- my $def_ref;
-
- exists($PARAMETER_LIST{$key})
- or &abort("unknown parameter: $key");
- $def_ref = $PARAMETER_LIST{$key};
- $spec = $key . ${$def_ref}[$OPT_ALIAS] . ${$def_ref}[$OPT_SPEC];
-
- return $spec;
-}
-
-### handle an option
-# parameter 1: a parameter/option key
-# parameter 2: the option value
-# return value: none
-
-sub handle_option {
- my $key = $_[0];
- my $value = $_[1];
- my $type;
-
- $type = ¶m_type($key);
-
- if ($type eq 'action') {
- &handle_action_opt($key, $value);
- } elsif ( $type eq 'bool' or $type eq 'three') {
- my $bool_value = $value ? $YES : $NO;
- &set_param_value($key, $bool_value);
- } elsif ( $type eq 'directory') {
- if (! &check_dir($value)) {
- &report(2, "$key requires an existing writable directory as an absolute path.");
- &abort("Illegal value: $value");
- }
- &set_param_value($key, $value);
- } elsif (defined(&type_enum_array($type))){
- &set_enum_param($key, $value);
- } else {
- &set_param_value($key, $value);
- }
-}
-
-### handle all action options
-# parameter 1: a option key
-# parameter 2: the option value
-# return value: none
-
-sub handle_action_opt {
- my $key = $_[0];
- my $value = $_[1];
-
- if ($key eq 'help') {
- &print_help;
-
- } elsif ($key eq 'version') {
- &print_version;
-
- } elsif ($key eq 'configure') {
- if ( -f $RC_FILENAME ) {
- &read_configuration($RC_FILENAME);
- }
- &configure;
- &write_configuration($RC_FILENAME);
- &print_configuration;
-
- } elsif ($key eq 'print_config') {
- if ( -f $RC_FILENAME ) {
- &read_configuration($RC_FILENAME);
- }
- &print_configuration;
-
- } else {
- &print_usage;
- exit 1;
- }
- exit 0;
-}
-
-### set a variable by a command line option to a possible values; abort on error
-# parameter 1: parameter key
-# parameter 2: value
-
-sub set_enum_value {
- my ($key, $value) = @_;
- my $type;
- my $enum_array_ref;
- my @allowed_values=();
-
- $type = ¶m_type($key);
- $enum_array_ref = &type_enum_array($type);
- &abort("Internal error: No value array for parameter $key.")
- if(!defined($enum_array_ref));
-
- ### find out if the given value is allowed
- foreach my $value_array_ref (${$enum_array_ref}) {
- if(${$value_array_ref}[0] eq $value) {
- ### found it, so it is okay!
- &set_param_value($key, $value);
- return;
- }
- }
-
- ### value is not listed, so not allowed
- ### make a list of all allowed values
- foreach my $value_array_ref (${$enum_array_ref}) {
- push(@allowed_values, ${$value_array_ref}[0]);
- }
-
- &report(2, "\n$key allows: " . @allowed_values . ".\n");
- &abort("Illegal value: $value");
-}
-
-### configure an existing parameter interactively
-# parameter 1: a parameter key
-# return value: none
-
-sub config_param {
- my $key = $_[0];
- my $type;
- my $new_value;
- my $current_value;
- my $description;
- my $explanation;
- my $question;
-
- ### get required information about this parameter
- $type = ¶m_type($key);
- $current_value = ¶m_value($key);
- ($description, $explanation, $question) = ¶m_config_output($key);
-
- ### tell the user the facts
- print "\n\n--------------------------------------------\n";
- print "Parameter: ".$key."\n";
- print $description."\n\n";
- print $explanation."\n\n" if($explanation ne "");
-
- ### ask him what he wants
- if ($type eq 'bool') {
- $new_value=&question_ynu($question, $current_value, $NO);
- } elsif ($type eq 'three') {
- $new_value=&question_ynu($question, $current_value, $YES);
- } elsif ($type eq 'directory') {
- $new_value=&input_dir($question, $current_value, $YES);
- } elsif ($type eq 'text') {
- $new_value=&input_text($question, $current_value);
- } elsif ($type eq 'integer') {
- $new_value=&input_number($question, $current_value,
- $NUM_PARAM_MIN, $NUM_PARAM_MAX);
- } else {
- my $enum_array_ref;
-
- $enum_array_ref=&type_enum_array($type);
- if (! defined($enum_array_ref)) {
- &abort("Do not know how to configure this parameter: $key (type: $type)");
- }
-
- $new_value=&choose_value($question,$current_value,$enum_array_ref);
- }
-
- ### store his choice
- &set_param_value($key, $new_value);
-}
-
-### save configuration in rc file
-# parameter 1: file name
-# return value: none
-
-sub write_configuration {
- my $file_name = $_[0];
- my $date;
-
- open(RCFILE, ">$file_name") or
- &abort("Could not open configuration file for writing ($file_name)");
- select RCFILE;
-
- $date = `date`;
- chomp($date);
-
- print "# Configuration file for $MYNAME V$MYRELEASE\n";
- print "# Generated $date by $MYUSER on $MYHOSTNAME\n";
- print "$RCVERSION_STRING=$MYRCFILE_VERSION\n";
-
- foreach my $key (@PARAMETER_ORDER) {
- my $value = $CONFIGURATION{$key};
- if(&full_param($key)) {
- print $key.'='.$value."\n";
- }
- }
-
- print "# EOF\n";
- select STDOUT;
- close RCFILE;
-}
-
-### print the configuration parameters
-
-sub print_configuration {
- print "\nConfiguration for $MYNAME V$MYRELEASE\n";
-
- foreach my $key (@PARAMETER_ORDER) {
- my $value = $CONFIGURATION{$key};
- if(&full_param($key)) {
- print $key.'='.$value."\n";
- }
- }
-
- print "\n";
-}
-
-### load parameters from rc file
-# parameter 1: file name
-# return value: version of read rc file or 0 if no version given
-
-sub read_configuration {
- my $file_name = $_[0];
- my $file_version= 0;
-
- &check_file($file_name, "Could not access configuration file");
- open(RCFILE, "<$file_name") or
- &abort("Could not open configuration file for reading ($file_name)");
-
- while (<RCFILE>) {
- chomp;
- if( /^([^#=]+)=(.*)$/ ) {
- if( exists $CONFIGURATION{$1} ) {
- $CONFIGURATION{$1} = $2;
- } elsif ( $1 eq $RCVERSION_STRING ) {
- $file_version = $2;
- } else {
- print "Ignoring unknown parameter in RC file: $1=$2\n";
- }
- }
- }
- close RCFILE;
-
- return $file_version;
-}
-
-### print script version
-
-sub print_version {
- print "\n$MYNAME Version $MYRELEASE\n";
-}
-
-###################### Specific functions (for use with this script only)
-
-### print usage of command
-
-sub print_usage {
- print "\nUsage: $MYNAME [OPTIONS] DOCUMENT.lyx\n";
- print " $MYNAME [OPTIONS] DOCUMENT[.tex]\n\n";
- print " $MYNAME -c | --configure modify/set up configuration\n";
- print " $MYNAME -h | --help give a short help\n";
- print " $MYNAME -o | --print_config print current configuration\n";
- print " $MYNAME -v | --version print my version\n\n";
-}
-
-### print command help
-
-sub print_help {
- &print_version;
- &print_usage;
-
- foreach my $key (@PARAMETER_ORDER) {
- my @param_def = @{$PARAMETER_LIST{$key}};
- my $description = $param_def[$DESCRIPTION];
- my $takes_value = $param_def[$OPT_SPEC] =~ /[=:]/ ? $TRUE : $FALSE;
- my $negation = $param_def[$OPT_SPEC] eq '!' ? $TRUE : $FALSE;
- my $alias = $param_def[$OPT_ALIAS];
-
- $alias =~ s/\|(([a-zA-Z])(\||$))/ | -$1/g;
- $alias =~ s/\|(([a-zA-Z][a-zA-Z0-9_]+)(\||$))/ | --$1/g;
-
- print "--";
- print "[no]" if($negation);
- print $key.$alias;
- print " VALUE" if ($takes_value);
- print ":\n ".$description."\n\n";
- }
- print "\n";
-}
-
-### configure all tex2pdf parameters interactively
-# parameters: none
-# return value: none
-
-sub configure {
-
- print "\n--------------------------------------------------------\n";
- print "\n***** Configuration for $MYNAME *****\n\n";
- print "The following answers are considered as defaults in later ";
- print "executions\n";
- print "of $MYNAME. You can change these values by using the option ";
- print "--configure \nagain.";
- print "Additionally, all command-line options override these settings.\n";
- print "Many parameters can be set to '$NIL' or '$UNDEF'. This means that NO";
- print "\nvalue at all (not even an empty value) is passed over to the ";
- print "called\napplication (e.g. latex package hyperref).\n";
-
- $NUM_PARAM_MIN=1;
- $NUM_PARAM_MAX=9;
-
- foreach my $key (@PARAMETER_ORDER) {
- if(&full_param($key)) {
- &config_param($key);
- }
- }
-
- print "\nConfiguration for $MYNAME finished.\n\n";
-}
-
-### check if the most important executables are installed on the system
-# parameters: none
-
-sub check_commands {
- my $exec_epstopdf;
- ### check for which command
- &checkCommand("which","You can switch off all command checks to fix this.");
-
- ### pdftex executables
- # Homepage: http://tug.org/applications/pdftex
- &checkCommand("pdflatex","See pdftex homepage for details: http://tug.org/applications/pdftex");
- &checkCommand("epstopdf","See pdftex homepage for details: http://tug.org/applications/pdftex");
- $exec_epstopdf = `which epstopdf`;
- chomp $exec_epstopdf;
- my $compat = "-dCompatibilityLevel=1\\.1";
- if (defined($ENV{'GS_OPTIONS'}) && $ENV{'GS_OPTIONS'} =~ /$compat/o) {
- &report(9, "Good: ghostscript option '-dCompatibilityLevel=1.1' detected "
- ."in\n'\$GS_OPTIONS'.");
- } elsif (&grep_file($exec_epstopdf, $compat, $TRUE) > 0) {
- &report(9, "Good: ghostscript option '-dCompatibilityLevel=1.1' detected "
- ."in\n'$exec_epstopdf'.");
- } else {
- &report(4, "\nWARNING: no ghostscript option '-dCompatibilityLevel=1.1' "
- ."in\n'$exec_epstopdf'.\n"
- ."You might run into trouble with the conversions of bitmaps.\n"
- ."Adjusting epstopdf or setting the environment variable GS_OPTIONS "
- ."to \n".'"$GS_OPTIONS -dCompatibilityLevel=1.1" before calling this '
- ."script\nmight help in this case.\n");
- }
-
- if ( ¶m_value('thumbpdf') eq $YES ) {
- &checkCommand("thumbpdf","You can switch off thumbpdf support to fix this.");
- }
-
- if ( ¶m_value('ppower') eq $YES ) {
- &checkCommand("ppower","You can switch off ppower support to fix this.");
- }
-
- ### authorindex perl script
- if ( ¶m_value('authorindex') eq $YES ) {
- &checkCommand("authorindex","You can switch off authorindex support to fix this.");
- }
-
- ### bibtex executable
- if ( ¶m_value('bibtex') ne $NO or ¶m_value('gloss') ne $NO) {
- &checkCommand("bibtex","You can switch off BibTeX support to fix this.");
- }
-}
-
-#### generate the tmp file name from the original tex filename
-#### and make sure that they are not the same
-# parameter 1: orignal filename (with or without a path or .tex)
-# parameter 2: path for the tmp file (default: doc path)
-# return value: tmp name
-
-sub reserve_tmp_texname {
- my $original_name = $_[0];
- my $tmp_path = $_[1];
- my $tmp_base_suffix = ¶m_value('tmp_base_suffix');
- my $overwrite = ¶m_value('overwrite');
- my $original_path;
- my $original_base;
- my $suffix;
- my $pathed_tmp_base;
- my @existing_files;
-
- # separate path, base and suffix
- ($original_base,$original_path,$suffix) = fileparse($original_name, '\.tex');
-
- # set the path of the tmp file
- if(!$tmp_path) {
- $tmp_path=$original_path;
- } else {
- $tmp_path .= '/' if( $tmp_path ne "" and ! ($tmp_path =~ m#/$#) );
- }
-
- # abort if no absolute path is given
- if( index($tmp_path, "/") != 0 ) {
- &abort("Internal error: Illegal argument for reserve_tmp_texname:".
- "Given file has no absolute path: $original_name");
- }
-
- # make sure that tmp_base_suffix is set correctly
- if($tmp_base_suffix eq "") {
- &abort("Temporary filename base suffix is empty.");
- }
-
- $pathed_tmp_base = $tmp_path.$original_base.$tmp_base_suffix;
-
- # make sure no file with this base exists in this directory
- @existing_files = glob "$pathed_tmp_base.*";
- if (@existing_files != 0) {
- &report(3, "Problems detected while reserving temporay file name!\n",
- "In this directory are already files with this basename.\n",
- "A list of the conflicting, existing files:\n",
- join("\n", @existing_files), "\n");
- if ($overwrite eq $YES) {
- &report(4, "As you have activated the parameter 'overwrite' I will "
- ."continue.\n",
- "However, in order to protect the existing files I will not\n",
- "delete any files with this basename at the final clean-up.");
- } else {
- &report(2, "You could activate the parameter 'overwrite' or remove ",
- "the\n corresponding files in order to avoid these problems.");
- &abort("No temporary name found for $original_name.");
- }
- } else {
- push(@TMP_TEX_FILES, $pathed_tmp_base);
- }
-
- return $pathed_tmp_base.$suffix;
-}
-
-### generate LaTeX file from LyX document with LyX itself
-# parameter ($1): Lyx document
-# parameter ($2): Latex document
-
-sub generate_tex_file {
- my $lyx_doc = $_[0];
- my $tex_doc = $_[1];
- my $lyx_dir;
- my $lyx_output;
- my $lyx_exec=¶m_value('lyx_exec');
-
- $lyx_dir = ¶m_value('lyxrc_path');
- $lyx_dir .= '/' if( ! ($lyx_dir =~ m#/$#) );
- $lyx_dir .= '/' if( ! ($lyx_dir =~ m#/$#) );
-
- ### Check if LyX file can be accessed
- &check_file($lyx_doc,"Cannot read the specified LyX document!");
-
- ### Check if LaTeX file exists and is newer than the LyX file
- if ( -f $tex_doc and -M $tex_doc < -M $lyx_doc ) {
- &report(4, "\nLaTeX file is newer than LyX document ($lyx_doc).\n",
- "Using existing TeX file: $tex_doc\n",
- "Remove it to force its new generation.");
- } else {
- ### export LaTeX file with LyX (needs a display!)
- &checkCommand($lyx_exec, "Cannot generate LaTeX document without LyX!");
- &report(6, "\nExporting LaTeX file");
-
- ### move some files out of the way that stop LyX from exporting
- foreach my $file ($lyx_dir."lyxpipe.out",$lyx_dir."lyxpipe.in",$tex_doc) {
- if ( -f $file ) { rename($file, $file.'~'); }
- }
-
- $lyx_output = `$lyx_exec --export latex $lyx_doc 2>&1`;
-
- ### check if LaTeX file now really exists
- if ( ! -f $tex_doc ) {
- &report(2, "Lyx Output:\n$lyx_output");
- &report(2, "\nSorry. I cannot find '$tex_doc'.");
- &abort("The LaTeX document was not generated by LyX!");
- } else {
- &report(8, "Lyx Output:\n$lyx_output");
- }
- }
-}
-
-#### search TeX document for a certain text tag (e.g. author, title)
-# parameter 1: file to parse
-# parameter 2: full TeX tag name
-# return value: list of the contents strings of all matching tags
-
-sub extract_tag_contents {
- my $source=$_[0];
- my $tag_name=$_[1];
- my $contents;
- my @results=();
- my $error_message="Could not read TeX document to extract $tag_name";
-
- &check_file($source, $error_message.'.');
- open(EXTRACT_SOURCE, "<$source") or
- &abort($error_message." ($source).");
-
-
- while(<EXTRACT_SOURCE>) {
- ### ignore comments
- s/(^|[^\\])%.*/$1/;
- # ignore \thanks{}
- s/\\thanks\{.*?\}//g;
- # change \and to and
- s/\\and/ and/g;
-
- $contents .= $_;
- }
-
- close EXTRACT_SOURCE;
-
- $_ = $contents;
-
- # add contents of all occurences of this tag in a line to result list
- while ( /\\($tag_name)(\[[^]]*?\])*?{+([^{}]*?)}/s ) {
- my $text = $3;
- $_ = $';
- # remove newlines
- $text =~ s/\n//g;
- $text="" if (!defined($text));
- push(@results, $text);
- }
-
- return @results;
-}
-
-#### search for filenames in given TeX Tag in entire document
-### skip all comments and duplicates while parsing
-# parameter 1: file to parse
-# parameter 2: full TeX tag name
-# parameter 3: reference to a list of possible filename suffixes (without '.')
-# parameter 4: regexp for suffix to ignore when specified in TeX file
-# (undef if not used)
-# return value: list of identified files
-
-sub identify_files {
- my $source=$_[0];
- my $tag_name=$_[1];
- my @suffixes=@{$_[2]};
- my $ignore_suffix=$_[3];
- my @matched_tags;
- my @found_files=();
- my $regexp_suffixes;
-
- # create one large regexp from given suffixes and escape dots in them
- $regexp_suffixes= '.('.join('|', @suffixes).')';
- $regexp_suffixes =~ s/\./\\./g;
-
- @matched_tags = &extract_tag_contents($source, $tag_name);
-
- foreach my $tag_contents (@matched_tags) {
- my $path;
- my $base;
- my $suffix;
- my $kpse_result;
- my $working_dir = cwd."/";
-
- ($base,$path,$suffix) = fileparse($tag_contents, $regexp_suffixes);
-
- # if a suffix is specified in the tag_contents handle it as requested
- #
- # 1. $suffix: TRUE if $suffix is defined and not of zero length
- # means: a valid suffix has been found in the filename
- # 2. defined($ignore_suffix): TRUE if $ignore_suffix is defined
- # means: a regexp for suffixes to be ignored has been specified as
- # parameter4
- # 3. $suffix =~ /$ignore_suffix/: TRUE if $suffix matches the regexp
- # means: the suffix in the filename is wanted to be ignored
- #
- # The IF statement will be executed when:
- # a valid suffix has been found in the filename (1)
- # AND regexp for suffixes to be ignored has NOT been specified (not 2)
- # OR
- # a valid suffix has been found in the filename (1)
- # AND regexp for suffixes to be ignored has been specified (2)
- # AND the suffix in the filename is NOT wanted to be ignored (not 3)
- #
- # The stuff that is executed if the entire IF statement is TRUE does the
- # following: accept the found suffix and consider it as the only possible
- # file name.
- if($suffix and not (defined($ignore_suffix) and $suffix =~ /$ignore_suffix/)){
- $kpse_result=`kpsewhich $tag_contents`;
- # print warning and skip this tag if kpsewhich could not find it
- if (!$kpse_result) {
- &report(4, "WARNING - Could not identify referenced file:\n",
- " Ignoring '$tag_contents'.");
- next;
- }
- } else {
- # if there is a '.' in the basename assume that this is a reference
- # to a file of another type and skip it
- if( $base =~ /\./ ) {
- &report(9, "Found an unknown extension. Ignoring '$tag_contents'.");
- next;
- }
-
- # search for all possible files with allowed suffixes
- foreach my $allowed_suffix (@suffixes) {
- if (not $allowed_suffix =~ /[\]\)\(\|\[\\]/ ) {
- # suffix is not a regexp, but a real extension
- my $possible_file= $path.$base.'.'.$allowed_suffix;
- $kpse_result=`kpsewhich $possible_file`;
- if ($kpse_result) {
- last;
- }
- }
- }
- }
-
- # if kpsewhich could not find any file with an allowed suffix
- # assume that this reference is of a different type and skip it
- # quietly
- if (!$kpse_result) {
- &report(9, "No suitable file found. Ignoring '$tag_contents'.");
- next;
- }
-
- # expand '.' in kpsewhich output to the current path
- $kpse_result =~ s#^\./#$working_dir#;
-
- # remove trailing newline
- chomp($kpse_result);
-
- # add file to the found file list if it is not already on it
- if( &array_index($kpse_result, @found_files) < 0 ) {
- push(@found_files, $kpse_result);
- }
- }
-
- return @found_files;
-}
-
-### Build a list of all files which are included from the root file.
-# This function recurses, and is maybe smart enough to detect cycles.
-# Be sure to set REF_DOCS to the empty string prior to calling this.
-# parameter 1: tex file to start with
-# no return value
-# result is appended to global variable @REF_DOCS
-
-sub get_file_list {
- my $source = $_[0];
- my @imports = ();
-
- # This is the cycle avoidance logic.
- if ( &array_index($source, @REF_DOCS) < 0 ) {
- # Make sure the file can be accessed
- &check_file($source, "Included TeX file seems not to be available. Path problem?");
-
- # Save the argument in the list of files.
- push(@REF_DOCS, $source);
-
- # Get the list of files included by the argument.
- @imports=&identify_files($source, 'include|input', ['tex']);
-
- # Recurse.
- foreach my $file (@imports) {
- if( ! ($file =~ /\.tex$/) ) { $file .= '.tex'; }
- &get_file_list($file);
- }
- }
-}
-
-### do the required modifications in the LaTeX preamble
-# parameter 1: original preamble from the source file
-# lines before \begin{document} tag (without this tag)
-# parameter 2: reference to hyperref parameter list
-# return value: adjusted preamble
-
-sub adjust_preamble {
- my $preamble = $_[0];
- my $hyperref_params_ref = $_[1];
- my $extra_code;
- my $result;
-
- $_ = $preamble;
-
- # protect pdflatex execution mode
- s/^(\\batchmode)$/% $1/m;
-
- # insert a4paper in the documentclass when a4wide is used
- # fixes problem that hyperref defaults to letter otherwise
- if ( /^[^%]*\\usepackage(\[widemargins\])?\{(a4|a4wide)\}/m ) {
- # check if package parameters with [] brackets are present
- if ( not s/^(\\documentclass\[.*?)\]/$1,a4paper]/m ) {
- s/^\\documentclass/$&\[a4paper\]/m;
- }
- }
-
- ### collect additional LaTeX code
-
- $extra_code = "\n" . '\usepackage{pslatex}' . "\n";
-
- if ( ¶m_value('thumbpdf') eq $YES ) {
- $extra_code .= '\usepackage{thumbpdf}' . "\n";
- } else {
- $extra_code .= "% no thumbpdf support\n";
- }
-
-# if ( ¶m_value('ppower') eq $YES ) {
-# $extra_code .= '\usepackage{mpmulti}' . "\n";
-# } else {
-# $extra_code .= "% no ppower support\n";
-# }
-
- if ( ¶m_value('authorindex') eq $YES ) {
- $extra_code .= '\usepackage[pages]{authorindex}' . "\n";
- $extra_code .= '\let\cite=\aicite' . "\n";
- } else {
- $extra_code .= "% no authorindex support\n";
- }
-
- $extra_code .= '\makeatletter' . "\n";
- $extra_code .= '\usepackage[' . join(',', @$hyperref_params_ref)
- . ']{hyperref}' . "\n";
- $extra_code .= '\makeatother' . "\n";
-
- ### insert the extra LaTeX code directly after documentclass
- m/^(\\documentclass)(\[[^]]*\])?(\{.*\})/m;
- return $` . $& . $extra_code . $';
-}
-
-### adjust all filenames in the LaTeX code to the tmp files
-# parameter 1: original LaTeX code from the source file
-# return value: adjusted code
-
-sub adjust_filenames {
- my $code = $_[0];
- my $tmp_suffix = ¶m_value('tmp_base_suffix');
- my $result;
-
- $_ = $code;
-
- # cut off the suffix of eps, ps, *.gz and pstex graphics
- s/((\\includegraphics)(\[[^]]*?\])?(\{[^}]+?))\.(e?ps|pstex|e?ps\.gz)\n?\}/$1}/sg;
-
- # replace the suffix 'pstex_t' with 'pdf_t'
- s/(\\input\{[^}]+?\.)pstex_t\n?\}/$1pdf_t}/sg;
-
- if ( ¶m_value('mtp_preamble') eq $NO ) {
- # cut off the suffix of mmp graphics
- s/(\\multiinclude(\[[^]]*?\])?\{[^}]+?)\.mmp\n?\}/$1}/sg;
- } else {
- # replace the suffix '.#' with '-mp.#'
- s/(\\includegraphics(\[[^]]*?\])?\{[^}]+?)\.(\d+?)\n?\}/$1$MTP_TMP_BASESUFFIX\.$3}/sg;
-
- # replace the suffix '.#' with '-mp.#'
- s/(\\convertMPtoPDF(\[[^]]*?\])?\{[^}]+?)\.(\d+?)\n?\}/$1$MTP_TMP_BASESUFFIX\.$3}/sg;
-
- # cut off optional suffix '.mmp' and append '-mp' in any case
- s/(\\multiinclude(\[[^]]*?\])?\{[^}]+?)(\.mmp)?\n?\}/$1$MTP_TMP_BASESUFFIX}/sg;
- }
-
- # insert the tmp_suffix in tex filenames
- # I assume that files with no extension are TeX files as well; correct?
- s#(\\(input|include)\{([^}]*?/)?[^}/.]+?)((\.tex)?\n?\})#$1$tmp_suffix$4#sg;
-
- return $_;
-}
-
-### Convert given tex file to the temp tex file we need for pdftex
-### major task is to change the reference in the tex files to the
-### corresponding tmp files
-# parameter 1: tex source file
-# parameter 2: tex tmp file
-# parameter 3: reference to hyperref parameter list or
-# 'undef' if preamble should not be changed
-
-sub convert_tex2tmp {
- my $source = $_[0];
- my $target = $_[1];
- my $hyperref_params_ref = $_[2];
- my $contents;
- my $preamble;
- my $body;
- my $adjust_preamble = defined($hyperref_params_ref) ? $YES : $NO;
- my $read_err_msg = "Could not read original TeX document to generate temporary document";
-
- ### open source and target file
- &check_file($source, $read_err_msg . '.');
- open(SOURCE_FILE, "<$source") or
- &abort($read_err_msg . " ($source).");
-
- ### read in the LaTeX source file
- $contents = "";
- while(<SOURCE_FILE>) {
- $contents .= $_;
- }
-
- close SOURCE_FILE;
-
- ### prepare the LaTeX code for PDF generation
- if ( $adjust_preamble eq $YES ) {
- $contents =~ m/^ *\\begin\{document\} *$/m;
- $preamble = $`;
- $body = $&.$';
- $preamble = &adjust_preamble($preamble, $hyperref_params_ref);
- $preamble = &adjust_filenames($preamble);
- } else {
- $preamble = "";
- $body = $contents;
- }
-
- $body = &adjust_filenames($body);
-
- ### write the new LaTeX target file
- open(TARGET_FILE, ">$target") or
- &abort("Could not open file to write temporary TeX document ($target).");
-
- print TARGET_FILE $preamble.$body;
-
- close TARGET_FILE;
-}
-
-### Convert the given EPS image to PDF
-# parameters $1: EPS image filename with absolute path
-# return value: none
-
-sub convert_eps2pdf {
- my $image = $_[0];
- my $image_path;
- my $image_base;
- my $image_name;
- my $suffix;
- my $image_target;
- my $zipped = 0;
- my $dummy;
-
- ($image_base,$image_path,$suffix) = fileparse($image, '\.eps', '\.ps', '\.pstex', '\.gz');
- if ($suffix eq "\.gz") {
- $zipped = 1;
- ($image_base,$dummy,$suffix) = fileparse($image_base, '\.eps', '\.ps', '\.pstex');
- }
- $image_name = $image_base . $suffix;
- $image_target = $image_path . $image_base . '.pdf';
-
- #### check if image file really exists
- #&check_file($image, "Could not convert referenced image.");
-
- ### return if image directory is not writeable
- if (! -w $image_path) {
- &report(4, "WARNING - Image directory not writable: $image_path\n",
- " Skipping '$image_name', assume you have converted it manually.");
- return;
- }
-
- if ( ! -f $image_target or -M $image_target > -M $image ) {
- &report(7, "Converting image $image_name to $image_target ...\n");
- if ($zipped > 0) {
- &system_command("gunzip -c $image | epstopdf -f -outfile=$image_target",
- $TRUE, 8, "epstopdf failed on $image_name");
- } else {
- &system_command("epstopdf -outfile=$image_target $image",
- $TRUE, 8, "epstopdf failed on $image_name");
- }
- if (¶m_value('delete_pdf_images') eq $YES) {
- push(@TMPFILES, $image_target);
- }
- } else {
- &report(7, "$image_base.pdf newer than $image_name, conversion skipped...");
- }
-}
-
-### Convert the given PSTEX_T file to PDF_T
-# parameters 1: PSTEX_T filename with absolute path
-# return value: none
-
-sub convert_pstex2pdf {
- my $pstex_file = $_[0];
- my $pstex_path;
- my $pstex_base;
- my $pstex_name;
- my $suffix;
- my $pstex_target;
- my @eps_images;
-
- ($pstex_base,$pstex_path,$suffix) = fileparse($pstex_file, ('\.pstex_t'));
- $pstex_name = $pstex_base . $suffix;
- $pstex_target = $pstex_path . $pstex_base . '.pdf_t';
-
- #### check if image file really exists
- #&check_file($pstex_file, "Could not convert referenced file.");
-
- ### return if directory is not writeable
- if (! -w $pstex_path) {
- &report(4, "WARNING - Directory not writable: $pstex_path\n",
- " Skipping '$pstex_name', assume you have converted it manually.");
- return;
- }
-
- # descend into file
- &report(7, "Converting file $pstex_name ...\n");
-
- # find included EPS image(s)
- @eps_images=&identify_files($pstex_file, 'includegraphics',
- ['pstex', 'pstex\.gz']);
-
- # create .pdf_t file
- &convert_tex2tmp($pstex_file, $pstex_target, undef);
-
- # put tmp file in the tmp file list
- push(@TMPFILES, $pstex_target);
-
- # convert image(s) to pdf
- foreach my $image (@eps_images) {
- &convert_eps2pdf($image);
- }
-}
-
-### Convert the given MP image to PDF
-# parameters $1: MP image filename with absolute path
-# return value: none
-
-sub convert_mp2pdf {
- my $image = $_[0];
- my $image_path;
- my $image_base;
- my $image_name;
- my $suffix;
- my $image_target;
- my $image_src;
- my @mps_fig=();
- my $mp_fig;
-
- ($image_base,$image_path,$suffix) = fileparse($image, '\.mp|\.mmp');
- $image_name = $image_base . $suffix;
- $image_src=$image_path . $image_base . $suffix;
-
- @mps_fig= &grep_file($image_path.$image_name,'beginfig',$TRUE);
- $_=$mps_fig[0];
- /(\d)/;
- $mp_fig=$1;
- if (¶m_value('mtp_preamble') eq $YES) {
- $image_target = $image_path . $image_base . $MTP_TMP_BASESUFFIX . '.' . $mp_fig;
- $image_name=$image_base.$MTP_TMP_BASESUFFIX.$suffix;
- } else {
- $image_target = $image_path . $image_base . '.' . $mp_fig;
- }
-
- #### check if image file really exists
- #&check_file($image, "Could not convert referenced image.");
-
- ### return if image directory is not writeable
- if (! -w $image_path) {
- &report(4, "$MYNAME: WARNING - Image directory not writable: $image_path\n",
- " Skipping '$image_name', assume you have converted it manually.");
- return;
- }
-
- if ( ! -f $image_target
- or (-M $image_target > -M $image_src)
- or ( ( ¶m_value('mtp_preamble') eq $YES)
- and (-M $image_target > -M $image_path.$MTP_PREAMBLE_FILENAME) ) ) {
- &report(7, "Converting image $image_name ...\n");
- my $working_dir = cwd."/";
- chdir("$image_path") or &abort("cannot cd to $image_path($!)");
- if ( ¶m_value('mtp_preamble') eq $YES ) {
- &modify_mp_file($image_base,$suffix);
- }
- &system_command("mpost $image_name",
- $TRUE, 8, "mpost failed on $image_name");
- chdir("$working_dir") or &abort("cannot cd to $working_dir($!)");
- if (¶m_value('delete_pdf_images') eq $YES) {
- push(@TMPFILES, $image_target);
- }
- } else {
- if ( ¶m_value('mtp_preamble') eq $YES ) {
- &report(7, "$image_base$MTP_TMP_BASESUFFIX.$mp_fig newer than $image_base$suffix, conversion skipped...");
- } else {
- &report(7, "$image_base.$mp_fig newer than $image_base$suffix, conversion skipped...");
- }
- }
-}
-
-### Convert the given MP image to PDF
-# parameters $1: MP image filename with absolute path
-# return value: none
-
-sub modify_mp_file {
- my $base=$_[0];
- my $suffix=$_[1];
- my $preamble_file=$MTP_PREAMBLE_FILENAME;
-
- my $mp_source=$base.$suffix;
- my $mp_target=$base.$MTP_TMP_BASESUFFIX.$suffix;
-
- ### open source and target file
- open(SOURCE_FILE, "<$mp_source") or
- &abort("Could not open $mp_source to add $preamble_file ($mp_source).");
-
- open(TARGET_FILE, ">$mp_target") or
- &abort("Could not open $mp_target to add $preamble_file ($mp_source).");
-
- open(PREAMBLE_FILE, "<$preamble_file") or
- &abort("Could not open $preamble_file to be added to metapost files ($mp_source).");
-
- ### set target file as stdout
- select TARGET_FILE;
- print 'verbatimtex' . "\n";
- print '%&latex' . "\n"; # This forces metapost to use latex in the compilation
- print '\documentclass[english]{article}' . "\n"; # we have to decide if this sentence goes in preamble.cfg or here
- # english must be added
- # to preamble in order to
- # make work mpost, why ???
- while(<PREAMBLE_FILE>) {
- print $_
- }
- print '\begin{document}' . "\n"; # we have to decide if this sentence goes in preamble.cfg or here
- print 'etex' . "\n";
- while(<SOURCE_FILE>) {
- print $_
- }
- print 'verbatimtex' . "\n";
- print '\end{document}' . "\n";
- print 'etex' . "\n";
-
- ### set STDOUT as stdout again
- select STDOUT;
-
- ### close files
- close SOURCE_FILE;
- close TARGET_FILE;
- close PREAMBLE_FILE;
-
-}
-
-
-### Convert included images to pdf
-# parameter 1: tex source file
-# no return value
-
-sub convert_images {
- my $tex_source=$_[0];
- my @pstex_file_list;
- my @image_list;
- my @mp_image_list;
- my @mmp_image_list;
- my @major_suffixes;
- my $ignore_regexp;
-
- &report(6, "\nConverting images referenced in $tex_source.");
-
- ##### Get images of major type from the source file
- @major_suffixes = (@BITMAP_SUFFIXES, $PDF_ORIG_SUFFIX, @EPS_SUFFIXES);
- $ignore_regexp = '.('.join('|',@EPS_SUFFIXES).')';
- $ignore_regexp =~ s/\./\\./g;
-
- &report(6, "\nScanning for major image types (".join(', ',@major_suffixes)."):");
- @image_list = &identify_files($tex_source,'includegraphics',
- \@major_suffixes, $ignore_regexp );
-
- if ( @image_list > 0 ) {
- &report(7, join("\n", @image_list));
- } else {
- &report(7, "None.");
- }
-
- ##### Get PSTEX_T files from the source file
- &report(6, "\nScanning for PSTEX_T files (.pstex_t):");
- @pstex_file_list=&identify_files($tex_source, 'input', ['pstex_t']);
- if ( @pstex_file_list > 0 ) {
- &report(7, join("\n", @pstex_file_list));
- } else {
- &report(7, "None.");
- }
-
- ##### Get MP images from the source file
- &report(6, "\nScanning for MP images (.mp):");
- @mp_image_list=&identify_files($tex_source,
- 'convertMPtoPDF|includegraphics',['mp','(\d+)'],'\.(\d+)');
- # FIXME
- # fixed for now by ignoring strange extension in identify_files
- #
- # the above could cause problems as identify_files is expecting a list of
- # real extensions and not of regexps
- # maybe the only way to fix this is to adjust identify_files to ignore
- # invalid extension when testing them with kpsewhich
- # ALTERNATIVE: design identify_files to use preffered_suffixes instead
- # of ignore_suffixes
-
- if ( @mp_image_list > 0 ) {
- &report(7, join("\n", @mp_image_list));
- } else {
- &report(7, "None.");
- }
-
- ##### Get MMP images from the source file
- &report(6, "\nScanning for MMP images (.mmp):");
- @mmp_image_list=&identify_files($tex_source,'multiinclude',['mmp']);
- if ( @mmp_image_list > 0 ) {
- &report(7, join("\n", @mmp_image_list));
- } else {
- &report(7, "None.");
- }
-
- ### Convert EPS images to PDF, copy pdf.orig image files to pdf,
- ### and simply ignore all other
- if ( @image_list > 0) {
- my $handled_suffixes;
-
- &report(6, "\nProcessing images of major types:");
-
- # create one large regexp from suffixes and escape dots in them
- $handled_suffixes = '.('.join('|',(@EPS_SUFFIXES, $PDF_ORIG_SUFFIX)).')';
- $handled_suffixes =~ s/\./\\./g;
-
- foreach my $image (@image_list) {
- my $path;
- my $base;
- my $suffix;
- ($base,$path,$suffix) = fileparse($image, $handled_suffixes);
- if (not $suffix) {
- &report(7, "No special handling required for image: $base$suffix");
- } elsif ($suffix eq ('.'.$PDF_ORIG_SUFFIX) ) {
- my $image_target = $path.$base.'.pdf';
-
- if ( ! -f $image_target or -M $image_target > -M $image ) {
- &report(7, "Create temporary PDF file from original: $base$suffix");
- copy($image, $image_target)
- or &abort("Could not create tmp file: $!");
- if (¶m_value('delete_pdf_images') eq $YES) {
- push(@TMPFILES, $image_target);
- }
- } else {
- &report(7, "$base.pdf newer than $base$suffix, copy skipped ...");
- }
- } else {
- &convert_eps2pdf($image);
- }
- }
- }
-
- ### Convert all PSTEX_T files to PDF_T
- if ( @pstex_file_list > 0 ) {
- &report(6, "\nConverting pstex_t docs to pdf_t docs");
- foreach my $image (@pstex_file_list) {
- &convert_pstex2pdf($image);
- }
- }
-
- ### Convert all MP images to PDF
- if ( @mp_image_list > 0) {
- &report(6, "\nConverting MP images to PDF");
- foreach my $image (@mp_image_list) {
- &convert_mp2pdf($image);
- }
- }
-
- ### Convert all MMP images to PDF
- if ( @mmp_image_list > 0) {
- &report(6, "\nConverting MMP images to PDF");
- foreach my $image (@mmp_image_list) {
- &convert_mp2pdf($image);
- }
- }
-
- &report(6, "\nFinished converting for ${tex_source}.");
-}
-
-### run pdflatex
-# parameter 1: LaTeX file without extension
-# parameter 2: log-file where the full out put is stored
-# return value: 0 - no errors (no rerun); 1 - errors (rerun required)
-
-sub run_pdflatex {
- my $texfile=$_[0];
- my $logfile=$_[1];
- my @errors=();
- my $exit_status=0;
- my $extra_options=¶m_value('pdftex_opts');
-
- if( !defined($extra_options) or $extra_options eq $NIL ) {
- $extra_options = "";
- }
-
- &report(7, "Running pdflatex. This may take a while.\n");
- system("pdflatex --interaction nonstopmode $extra_options $texfile > $logfile 2>&1");
- $exit_status=$?;
- &report(7, "Pdflatex finished. Errors:");
-
- ### extract all errors and warnings from the log file
- @errors = &grep_file($logfile, '(Emergency stop|Error|Warning).*:');
-
- ### make sure thumbpdf package does not spoil rerun detection
- ### as it will be processed very last
- if(grep(/Package thumbpdf/, @errors) == @errors) { @errors=(); }
-
- if ( @errors != 0 or $exit_status != 0 ) {
- if ( grep(/Emergency stop/, @errors) != 0 ) {
- &report(2, &file_tail($logfile,10));
- &report(2, "\nSee $logfile for details.");
- &abort("Fatal error occured. I am lost.");
- }
- if( @errors != 0 ) {
- &report(8, @errors);
- } else {
- &report(8, &file_tail($logfile,10));
- }
- &report(7, "\nSee $logfile for details.");
- return $FALSE;
- } else {
- &report(7, "None detected (log file: $logfile).");
- return $TRUE;
- }
-}
-
-#### run bibtex if BIBTEX=$YES or a bibliography tag is found
-# included tex files are not parsed for a bibliography
-# parameter 1: filename of the aux file without .aux suffix
-# parameter 2: log-file where the full out put is stored
-
-sub handle_bibtex {
- my $auxfile=$_[0];
- my $logfile=$_[1];
- my $run_bibtex=$FALSE;
- my $bibtex_param=¶m_value('bibtex');
-
- if ( $bibtex_param eq $YES ) {
- $run_bibtex=$TRUE;
- &report(7, "BibTeX parameter set to '$YES':");
- } else {
- &report(7, "Checking for BibTeX bibliography in main document: ");
- if( &grep_file($auxfile.'.tex', '^[^%]*\\\\bibliography{') != 0) {
- $run_bibtex=$TRUE;
- &report(7, "Bibliography detected.");
- } else {
- if ( @REF_DOCS > 0 ) {
- &report(7, "Checking for BibTeX bibliography in included documents:");
- foreach my $file (@REF_DOCS) {
- if( &grep_file($file, '^[^%]*\\\\bibliography{') != 0) {
- $run_bibtex=$TRUE;
- &report(7, "Bibliography detected.");
- } else {
- &report(7, "No bibliography detected in $file.");
- }
- }
- } else {
- &report(7, "No bibliography detected.");
- }
- }
- }
-
- if ( $run_bibtex ) {
- my @errors=();
- my $exit_status=0;
-
- &report(7, "Running bibtex. This may take a while.\n");
- system "bibtex $auxfile > $logfile";
- $exit_status=$?;
- &report(7, "Bibtex finished. Errors:");
-
- ### extract all errors and warnings from the log file
- @errors=&grep_file($logfile, 'error message');
-
- if ( @errors != 0 or $exit_status != 0 ) {
- &report(4, &file_tail($logfile));
- &report(4, "\nYou can switch off BibTeX support by setting the bibtex parameter accordingly.");
- } else {
- &report(7, "None detected (log file: $logfile).");
- }
- }
-}
-
-#### run bibtex on file.gls if BIBTEX=$YES or a bibliography tag is found
-# included tex files are not parsed for a bibliography
-# parameter 1: filename of the aux file without .aux suffix
-# parameter 2: log-file where the full out put is stored
-
-sub handle_gloss {
- my $auxfile=$_[0];
- my $logfile=$_[1];
- my $run_gloss=$FALSE;
- my $gloss_param=¶m_value('gloss');
- my $glsfile=$auxfile.'.gls';
-
- if ( $gloss_param eq $YES ) {
- $run_gloss=$TRUE;
- &report(7, "Gloss parameter set to '$YES':");
- } else {
- &report(7, "Checking for Gloss bibliography in main document: ");
- if( &grep_file($auxfile.'.tex', '^[^%]*\\\\printgloss{') != 0) {
- $run_gloss=$TRUE;
- &report(7, "Gloss bibliography detected.");
- } else {
- if ( @REF_DOCS > 0 ) {
- &report(7, "Checking for Gloss bibliography in included documents:");
- foreach my $file (@REF_DOCS) {
- if( &grep_file($file, '^[^%]*\\\\printgloss') != 0) {
- $run_gloss=$TRUE;
- &report(7, "Gloss bibliography detected.");
- } else {
- &report(7, "No gloss database detected in $file.");
- }
- }
- } else {
- &report(7, "No gloss database detected.");
- }
- }
- }
- if ( $run_gloss ) {
- my @errors=();
- my $exit_status=0;
-
- &report(7, "Running bibtex on $glsfile. This may take a while.\n");
- system "bibtex $glsfile > $logfile 2>&1";
- $exit_status=$?;
- &report(7, "Bibtex finished. Errors:");
-
- ### extract all errors and warnings from the log file
- @errors=&grep_file($logfile, 'error message');
-
- if ( @errors != 0 or $exit_status != 0 ) {
- &report(4, &file_tail($logfile));
- &report(4, "\nYou can switch off Gloss support by setting the gloss parameter accordingly.");
- } else {
- &report(7, "None detected (log file: $logfile).");
- }
- }
-}
-
-#### run thumbpdf command to make thumbnails
-# more informations: /usr/share/texmf/doc/pdftex/thumbpdf/readme.txt
-# parameter 1: LaTeX file without extension
-# parameter 2: log-file where the full out put is stored
-
-sub run_thumbpdf {
- my $texfile=$_[0];
- my $logfile=$_[1];
- my $exit_status=0;
-
- &report(7, "\nCreating thumbnails with 'thumbpdf'\n");
- &system_command("thumbpdf $texfile", $FALSE, 8,
- "thumbpdf failed.\n"
- ."I will continue, but maybe there will not be thumbs in the PDF doc.");
-
- if ( -f 'thumbpdf.log' ) {
- move('thumbpdf.log', $logfile);
- &report(7, "\nSee $logfile for details.");
- }
-
- ### store possible tmp files
- push(@TMPFILES, glob 'thumb???.png');
- push(@TMPFILES, 'thumbpdf.pdf');
- push(@TMPFILES, 'thumbdta.tex');
- push(@TMPFILES, $texfile.'.tpt');
-}
-
-
-#### run ppower command to make presentations
-# more informations:
-# parameter 1: LaTeX file without extension
-# parameter 2: log-file where the full out put is stored
-
-sub run_ppower {
- my $texfile=$_[0];
- my $logfile=$_[1];
- my $exit_status=0;
- my $infile;
- my $outfile;
- my $texfile_base;
- my $texfile_path;
- my $texfile_suffix;
-
- ##### Getting document name, suffix and path
- ($texfile_base,$texfile_path,$texfile_suffix) = fileparse($texfile,¶m_value('tmp_base_suffix'));
-
- $infile=$texfile_base.'.pdf';
- $outfile=$texfile_base.'_p4.pdf';
-
- &report(7, "\nPostprocessing PDF file with 'ppower'\n");
- if(&system_command("ppower $infile $outfile", $FALSE, 8,
- "ppower failed.\nI will continue, "
- ."but maybe there will not be pause effects in the PDF doc.")) {
- &report(7, "\nThe postprocessed pdf file is: $outfile\n");
- }
-
- if ( -f 'ppower.log' ) {
- move('ppower.log', $logfile);
- &report(7, "See $logfile for details.");
- }
-}
-
-#### run authorindex command to obtain an author index
-# more informations:
-# parameter 1: LaTeX file without extension
-# parameter 2: log-file where the full out put is stored
-
-sub run_authorindex {
- my $texfile=$_[0];
- my $logfile=$_[1];
- my $exit_status=0;
-
- &report(7, "\nProcessing file with 'authorindex'\n");
- &system_command("authorindex $texfile", $FALSE, 8,
- "authorindex failed.\nI will continue, "
- ."but maybe there will not be an author index in the PDF doc.");
-
- if ( -f 'authorindex.log' ) {
- move('authorindex.log', $logfile);
- &report(7, "\nSee $logfile for details.");
- }
-
-}
-
-
-##### read and analyse configuration and options and adjust basic variables
-##### accordingly
-#### The following sources are considered (last value overrides previous)
-## 1. general configuration (global variables in the script)
-## 2. private configuration (in user's RC file)
-## 3. command line options
-# parameters: none
-# return value: given document argument
-
-sub adjust_configuration {
- my $valid_rcfile = $FALSE;
- my %opt_specs =();
-
- ### Check number of arguments
- if ( @ARGV == 0 ) {
- &report(1, "\nI need at least one argument!");
- &print_usage;
- exit 1;
- }
-
- ##### command line options and private configuration files handling
-
- ### set parameters from rc file
- if ( -f $RC_FILENAME ) {
- my $rcfile_version;
- $rcfile_version = &read_configuration($RC_FILENAME);
- if( $rcfile_version == $MYRCFILE_VERSION ) {
- $valid_rcfile = $TRUE;
- } elsif ( $rcfile_version == 0 ) {
- &report(4, "Could not determine version of read RC file.");
- } else {
- &report(4, "Version of read RC file ($rcfile_version) and ",
- "this script ($MYRCFILE_VERSION) differs.");
- }
- }
-
- ### scan parameters
- foreach (keys %PARAMETER_LIST) {
- $opt_specs{&option_specifier($_)} = \&handle_option;
- }
- if(! GetOptions(%opt_specs)) {
- &print_usage;
- &abort("An error occured while processing command line options");
- }
-
- if( ! $valid_rcfile ) {
- &report(3,"No valid configuration file found. Please run '$MYNAME "
- ."--configure'.\nUsing default values for missing parameters in this "
- ."session.");
- }
-
- ### As the configuration process is done now, it is time to set the
- # global configuration flag
- $CONFIGURED = $TRUE;
-
- #### do some test in order to secure as good as possible that we will
- #### succeed before to much work was done and maybe some data as damaged
-
- ### make sure that tmp_base_suffix is not empty
- if ( ¶m_value('tmp_base_suffix') eq "" ) {
- &report(2, "\nCAUTION: Empty tmp_base_suffix would destroy the original files!");
- &abort("Parameter tmp_base_suffix is not set.");
- }
-
- ##### check for required commands
- if (¶m_value('check_commands') ne $NO ) {
- &check_commands;
- }
-
- ### Check number of arguments
- if ( @ARGV != 1 ) {
- &report(1, "\nWrong number of arguments. I need exactly one file.");
- &print_usage;
- exit 1;
- }
-
- return $ARGV[0];
-}
-
-#### prepare the logdir for the log files of the various called appplications
-
-sub prepare_logdir {
- my $log_dir= ¶m_value('logdir');
- my $my_new_log;
-
- ##### Preparing the LOGDIR
- if (! &check_dir($log_dir, "Could not create log directory", $YES)) {
- &abort("Please, set a different path and restart");
- }
-
- # make sure there is a slash at the end of the path
- $log_dir .= '/' if( ! ($log_dir =~ m#/$#) );
-
- if( <$log_dir/*.log> and ¶m_value('clean_logs') eq $YES ) {
- &report(6, "\nRemoving old log files ($log_dir).");
- unlink (<$log_dir/pdflatex-*.log>, <$log_dir/bibtex-*.log>,
- <$log_dir/gloss-*.log>, <$log_dir/thumbpdf-*.log>,
- <$log_dir/ppower-*.log>, <$log_dir/authorindex-*.log>,
- <$log_dir/tex2pdf-*.log>);
- } else {
- &report(6, "\nAll log files will be stored in ($log_dir).");
- }
-
- ### move my pre-configuration log file to specified log directory
- $my_new_log = "$log_dir/tex2pdf-$$.log";
- if ( move($MYLOGFILE, $my_new_log) ) {
- $MYLOGFILE = $my_new_log;
- } else {
- &report(3, "Could not move '$MYLOGFILE' to logdir: $!");
- }
-}
-
-##### analyse document argument
-#### process the one and only argument (besides the options) which specifies
-#### which LaTeX document the user wants to translate to PDF
-#### a lyx file will be translated to LaTeX first
-# parameter 1: argument
-
-sub process_doc_argument {
- my $argument = $_[0];
- my $doc_base;
- my $doc_path;
- my $arg_suffix;
-
- ##### Getting document name, suffix and path
- ($doc_base,$doc_path,$arg_suffix) = fileparse($argument, ('\.tex', '\.lyx'));
-
- if (! defined($arg_suffix) or $arg_suffix eq "") {
- $arg_suffix = '.tex';
- }
-
- ###### change working directory to document directory
- if ( $doc_path ne "" ) {
- chdir $doc_path;
- }
-
- ###### make DOCPATH an absolute path
- $doc_path = cwd.'/';
-
- ###### Cut off suffix and do lyx or tex specific stuff
- if ( $arg_suffix eq '.lyx' ) {
- # Lyx document argument: generate Latex document if required
- &generate_tex_file($doc_base.'.lyx', $doc_base.'.tex');
- } else {
- # LaTeX document argument: check access to given LaTeX document
- &check_file($doc_base.'.tex', "Cannot read the specified LaTeX document!");
- }
-
- return $doc_path.$doc_base.'.tex';
-}
-
-#### handle the dir of the input path if the document has one and
-# parameter 1: main tex doc
-# return value: absolute input path
-
-sub process_inputpath {
- my $texdoc = $_[0];
- my $doc_base;
- my $doc_path;
- my $doc_suffix;
- my $input_path;
- my @matches;
-
- ### Maybe the user has given us a different inputpath
- $input_path = ¶m_value('input_path');
- if(defined($input_path) and $input_path ne "") {
- &report(6, "Setting input path to specified directory: $input_path");
-
- &report(7, "Change working directory to input path.");
- chdir $input_path;
-
- return $input_path;
- }
-
- ##### Getting document name, suffix and path
- ($doc_base,$doc_path,$doc_suffix) = fileparse($texdoc, ('\.tex'));
-
- ###### change working directory to input_path if set
- # When the files' path (images, included documents, etc.) in your document is
- # relative to another directory than the PASSED document's directory.
- # This is useful when the calling application (e.g. LyX) generates a
- # temporary
- # TeX file and calls the tex2pdf with it instead of the original file.
-
- @matches=&extract_tag_contents($texdoc, 'def\\\\input@path');
- $input_path=$matches[0];
-
- ## check if input_path is ok
- if ($input_path) {
- &report(7, "Found an input path in the latex document: $input_path");
- if( &check_dir($input_path, 'The retrieved input@path seems not to be valid.', $NO)) {
- &set_param_value('input_path', $input_path);
- &report(7, "Change working directory to input path.");
- chdir $input_path;
- } else {
- &abort ('I am lost.');
- }
- } else {
- &report(4, "No input path in the latex document found.");
- &report(7, "Resources are expected to be relative to document's location: $doc_path");
- $input_path=$doc_path;
- }
-
- return $input_path;
-}
-
-#### set the working dir to the input path if the document has one and
-#### and determine the path for the result
-# parameter 1: main tex doc
-# parameter 2: absolute input path
-# return value: absolute path were the resulting pdf doc should be stored
-
-sub get_target_name {
- my $texdoc = $_[0];
- my $input_path=$_[1];
-
- my $doc_base;
- my $doc_path;
- my $doc_suffix;
- my $destination;
- my $pdf_path;
-
- ##### Getting document name, suffix and path
- ($doc_base,$doc_path,$doc_suffix) = fileparse($texdoc, ('\.tex'));
-
- ##### set the directory where the final pdf will be stored
- $destination=¶m_value('destination');
- $pdf_path=undef;
-
- if ($destination eq 'custom' ) {
- $pdf_path=¶m_value('custom_path');
- } elsif ($destination eq 'input') {
- $pdf_path=$input_path;
- } else {
- $pdf_path=$doc_path;
- }
-
- if( ! defined($pdf_path) or $pdf_path eq "" or ! &check_dir($pdf_path,
- 'The specified destination directory for the final PDF documents is not valid.', $NO)) {
- &report(7, "Using document's instead of destination path: $doc_path");
- $pdf_path=$doc_path;
- }
-
- # make sure there is a slash at the end of the path
- $pdf_path .= '/' if( ! ($pdf_path =~ m#/$#) );
-
- return $pdf_path.$doc_base.'.pdf';
-}
-
-### generate hyperref parameters from given settings
-# parameter 1: main tex doc
-# return_value: result
-
-sub generate_hyperref_params {
- my $texdoc = $_[0];
- my $para;
- my @params = ('pdftex');
-
- ##### Set title and author from main LaTeX document or parameters
- foreach my $info (('title', 'author')) {
- my $value;
-
- $value=¶m_value("$info");
- if (! defined($value) ) {
- my @matches=&extract_tag_contents($texdoc, $info);
- $value= $matches[0];
- if (! defined($value) ) {
- &report(4, "\nWARNING: Could not identify document's $info correctly.");
- &report(7, "Maybe you have used a LaTeX tag inside the $info which confuses me.\n",
- "Adjust the $info of the LaTeX file in order to avoid the problem or\n",
- "you could set the $info parameter manually.");
- $value= ¶m_value("default_$info");
- &report(7, "Using default-$info: $value");
- }
- }
- if (! defined($value) or $value eq $NIL ) {
- &report(7, "$info field set to $NIL - no value will be passed.");
- } else {
- &report(7, "Document's $info: $value");
- push(@params, "pdf$info={$value}");
- }
- }
-
- $para=¶m_value('paper');
- if ( $para ne $NIL ) { push(@params, $para); }
-
- $para=¶m_value('link_toc_page');
- if ( $para eq $YES ) { push(@params, 'linktocpage'); }
-
- $para=¶m_value('colorlinks');
- if ( $para ne $NIL ) {
- $para= $para eq $YES ? 'true' : 'false';
- push(@params, "colorlinks=$para");
- }
-
- if ( $para ne 'false' ) {
- foreach (('linkcolor', 'pagecolor', 'urlcolor', 'citecolor')) {
- $para=¶m_value($_);
- if ( $para ne $NIL ) { push(@params, "$_={$para}"); }
- }
- }
-
- $para=¶m_value('hyperref_args');
- if(defined($para) and $para ne "" and $para ne $NIL) {
- push(@params, $para);
- }
-
- return @params;
-}
-
-#### Prepare the main document and all referenced ones for the generation
-#### of the PDF document (including referenced images)
-# parameter 1: top level tex document
-# parameter 2: parameter list of hyperref parameters
-
-sub prepare_documents {
- my ($main_tex_doc, $input_path, @hyperref_params) = @_;
- @REF_DOCS=();
-
- ## get a name for the tmp tex file
- my $main_tmp_doc = &reserve_tmp_texname($main_tex_doc, $input_path);
-
- ## Get the list of imported files from the tex file
- &get_file_list($main_tex_doc);
-
- ## remove main file from list (first element; needs special handling)
- shift @REF_DOCS;
-
- ## tell user about the identified refereneced docs
- if ( @REF_DOCS > 0 ) {
- &report(7, "\nFound the following referenced TeX files:");
- foreach my $file (@REF_DOCS) {
- &report(7, ">>>>> $file");
- }
- } else {
- &report(7, "\nFound no referenced TeX files.");
- }
-
- ##### Generate adjusted temp tex files and convert all their images
- ## main doc
- &report(6, "\nGenerating main temporary LaTeX document: $main_tmp_doc");
- &convert_tex2tmp($main_tex_doc, $main_tmp_doc, \@hyperref_params);
- &convert_images($main_tex_doc);
-
- ## referenced docs
- foreach my $file (@REF_DOCS) {
- my $tmp_file = &reserve_tmp_texname($file);
-
- ### Insert pdf conversation tags in tex file and write it to tmp_file
- &report(7, "\nGenerating temporary LaTeX document: $tmp_file");
- &convert_tex2tmp($file, $tmp_file, undef);
- &convert_images($file);
- }
-
- return $main_tmp_doc;
-}
-
-##### Generate the final PDF document
-# parameter 1: filename of the source LaTeX document (with extension)
-
-sub generate_pdf_doc {
- my $source = $_[0];
- my $runno=1;
- my $rerun=$TRUE;
- my $doc;
- my $pdf_doc;
- my $base;
- my $path;
- my $suffix;
-
- my $max_run_no= ¶m_value('maxrun');
- my $min_run_no= ¶m_value('minrun');
- my $log_dir= ¶m_value('logdir');
- $log_dir .= '/' if( ! ($log_dir =~ m#/$#) );
- my $makeindex_options=¶m_value('makeindex_opts');
-
- # setting the log files for the output of pdflatex, bibtex, gloss,
- # thumbpdf, ppower and authorindex
- my $pdflog_base = $log_dir."pdflatex-$$-";
- my $bibtex_log = $log_dir."bibtex-$$.log";
- my $gloss_log = $log_dir."gloss-$$.log";
- my $thumbpdf_log = $log_dir."thumbpdf-$$.log";
- my $ppower_log = $log_dir."ppower-$$.log";
- my $authorindex_log = $log_dir."authorindex-$$.log";
-
- ##### Getting document name, suffix and path
- ($base,$path,$suffix) = fileparse($source, ('\.tex'));
- $doc = $path.$base;
- $pdf_doc = $base.'.pdf';
-
- ### run pdflatex until no more errors are reported (max MAXRUNNO)
- while ( $rerun and $runno <= $max_run_no )
- {
- &report(6, "\n************ Pdflatex run no. $runno *************");
- if ( &run_pdflatex($doc, $pdflog_base.$runno.'.log') == $TRUE
- and ( $min_run_no <= $runno )) {
- # no errors detected and min. no. of runs are done
- $rerun=$FALSE;
- } else {
- # errors appeared or max run no. has not been reached
- $rerun=$TRUE;
- }
-
- ### Execute BibTeX after first run if set (and required)
- if ( $runno == 1 and ¶m_value('bibtex') ne $NO ) {
- &report(6, "\n****************** BibTeX handling ***********************");
- &handle_bibtex($doc, $bibtex_log);
- }
-
- ### Execute BibTeX on file.gls after first run if set (and required)
- if ( $runno == 1 and ¶m_value('gloss') ne $NO ) {
- &report(6, "\n****************** Gloss handling ***********************");
- &handle_gloss($doc, $gloss_log);
- }
-
- ### generated index file exists
- if ( $runno == 1 and -f $doc.'.idx' and ¶m_value('force_index') ne $NO ) {
- if( !defined($makeindex_options) or $makeindex_options eq $NIL ) {
- $makeindex_options = "";
- }
- &report(6, "\n****************** Extra index generation ***************");
- &report(7, "Document seems to have an index. Generating ...\n");
- &system_command("makeindex $makeindex_options $doc.idx", $FALSE, 8,
- "makeindex failed.\nI will continue, "
- ."but maybe there will not be an index in the PDF doc.");
- }
-
- $runno += 1;
- }
-
- $rerun = $FALSE;
-
- ### if the authorindex option is switched on then run authorindex
- if ( ¶m_value('authorindex') eq $YES ) {
- &report(6, "\n****************** authorindex generation *****************");
- &run_authorindex($doc, $authorindex_log);
- }
-
- ### generated index file exists
- if ( -f $doc.'.idx' and ¶m_value('force_index') ne $NO ) {
- if( !defined($makeindex_options) or $makeindex_options eq $NIL ) {
- $makeindex_options = "";
- }
- &report(6, "\n****************** Extra index generation ***************");
- &report(7, "Document seems to have an index. Generating ...\n");
- &system_command("makeindex $makeindex_options $doc.idx", $FALSE, 8,
- "makeindex failed.\nI will continue, "
- ."but maybe there will not be an index in the PDF doc.");
- $rerun=$TRUE;
- }
-
- ### if the thumbpdf option is switched on then make thumbnails
- if ( ¶m_value('thumbpdf') eq $YES ) {
- &report(6, "\n****************** Thumbnail generation *****************");
- &run_thumbpdf($doc, $thumbpdf_log);
- $rerun=$TRUE;
- }
-
- ### One final pdflatex run if requested
- if ( $rerun ) {
- &report(6, "\n************ One final pdflatex run no. $runno *************");
- &run_pdflatex($doc, $pdflog_base.$runno.'.log');
- }
-
- ### if the ppower option is switched on then run ppower
- if ( ¶m_value('ppower') eq $YES ) {
- &report(6, "\n****************** ppower postprocess *****************");
- &run_ppower($doc, $ppower_log);
- }
-
- if ( ! -f $pdf_doc ) {
- &abort("\nThe new PDF file could not be generated: ".$pdf_doc);
- }
-
- return $pdf_doc;
-}
-
-################## Lift off !!!! (main part) ##################
-
-my $texdoc;
-my $doc_argument;
-my $input_path;
-my $target_name;
-my @hyperref_params;
-my $new_pdf_doc;
-my $tmp_tex_doc;
-
-&report(5, "\nScript starts ($MYRELEASE)");
-
-##### read and analyse configuration and options and adjust basic variables
-##### accordingly
-##### write RC file on config request
-#### use the finished configuration to get all further settings before we
-#### actually start doing something
-
-&report(5, "\nProcessing given parameters and arguments.");
-$doc_argument = &adjust_configuration;
-
-#### prepare the script to write some information to specified log files
-
-&report(5, "\nPreparing directory for log files.");
-&prepare_logdir;
-
-#### process the one and only argument (besides the options) which specifies
-#### which LaTeX document the user wants to translate to PDF
-#### a lyx file will be translated to LaTeX first
-
-&report(5, "\nAnalysing your document argument.");
-$texdoc = &process_doc_argument($doc_argument);
-
-#### we would like to get some more information from the actual
-#### main LaTeX document before we really start
-#### parse the document and try to get the info
-
-## translate hyperref settings to the actual package parameters
-
-&report(5, "\nSetting up parameters for hyperref.");
-@hyperref_params = &generate_hyperref_params($texdoc);
-
-## set the working dir to the input path if the document has one and
-
-&report(5, "\nProcessing input path for main tex document.");
-$input_path = &process_inputpath($texdoc);
-
-## determine the name for the result
-
-&report(5, "\nSetting the correct name for the result.");
-$target_name = &get_target_name($texdoc, $input_path);
-
-## as much as possible is prepared in advance at this point
-## so hopefully we will succeed in generating the PDF document
-
-##### real work starts NOW
-
-##### Generate adjusted temp tex files and convert all their images
-
-&report(5, "\nPreparing all documents and images.");
-$tmp_tex_doc = &prepare_documents($texdoc, $input_path, @hyperref_params);
-
-##### Generate the final PDF document
-
-&report(5, "\nProcessing the actual generation of the PDF document.");
-$new_pdf_doc = &generate_pdf_doc($tmp_tex_doc);
-
-##### Finalize
-move($new_pdf_doc, $target_name) or &abort("Could not move PDF file to final destination: $!");
-
-if ( ¶m_value('debug') eq $NO ) {
- &clean_up;
-} else {
- &print_temp_files;
-}
-
-&report(5, "\nThe new pdf file is: $target_name\n");
-
+++ /dev/null
-.Xrefs
-Makefile
-Makefile.in
-.deps
-TAGS
-balloc.c
-bitmap.c
-dir.c
-file.c
-fsync.c
-ialloc.c
-inode.c
-ioctl.c
-namei.c
-super.c
-symlink.c
-xattr.c
-patch-stamp
-sed-stamp
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=-DEXPORT_SYMTAB
-MODULE = extN
-modulefs_DATA = extN.o
-EXTRA_PROGRAMS = extN
-
-# NOTE: If you are not using a RedHat 12.5 or later kernel, then you need to
-# apply the "fixes" patch first, as it fixes a number of bugs in ext3.
-# It will be applied automatically by the extN build process, or you
-# can apply it to the source kernel tree and fix ext3 also. For chaos22
-# (or other RH < 12.5 kernels) use the "chaos22" patch instead.
-EXTN_FIXES = ../patches/patch-2.4.18-chaos22
-#EXTN_FIXES = ext3-2.4.18-fixes.diff
-EXTNP = htree-ext3-2.4.18.diff linux-2.4.18ea-0.8.26.diff
-EXTNP+= ext3-2.4.18-ino_sb_macro.diff extN-misc-fixup.diff
-EXTNC = balloc.c bitmap.c dir.c file.c fsync.c ialloc.c inode.c ioctl.c
-EXTNC+= namei.c super.c symlink.c
-EXTNI = extN_fs.h extN_fs_i.h extN_fs_sb.h extN_jbd.h quotaops.h
-EXTN_EXTRA = include/linux/xattr.h include/linux/extN_xattr.h fs/extN/xattr.c
-EXTN_EXTRA += include/linux/quotaops.h
-extN_SOURCES = $(EXTNC) xattr.c # punch.c
-extN_DEPENDENCIES = patch-stamp
-EXTRA_DIST = $(EXTNP) $(EXTN_FIXES) \
- extN-2.4.18-ino_sb_fixup.diff extN-2.4.18-exports.diff \
- $(wildcard extN.patch-*)
-DISTCLEANFILES = -r $(extN_SOURCES) sed-stamp patch-stamp *.orig *.rej
-SUB=-e "s/ext3/extN/g" -e "s/EXT3/EXTN/g" -e "s/extern __inline__/static inline/"
-
-distclean:
- cd .. && rm -f $(EXTN_EXTRA)
-
-include $(top_srcdir)/Rules
-
-# Following 2 vars are for buildind outside the source tree.
-extN_orig = $(top_builddir)/$(subdir)/extN.orig
-extN_include_orig = $(top_builddir)/$(subdir)/extN-include.orig
-
-# Create a fresh extN patch.
-# This is for when the patch-stamp target fails for your kernel.
-# Just edit the files until you like them, then do `make diff', and
-# it will create a specialized patch for your particular kernel.
-# Check it in, and the build should work for you without disrupting
-# the other developers.
-# Of course, the ideal is to merge changes so that the default patch
-# set works for nearly everybody. This is mainly for damage control.
-
-diff:
- $(RM) extN.patchT
- l='$(EXTNC)'; for f in $$l; do \
- echo "$$f"; \
- (diff -u $(extN_orig)/$$f extN/$$f) >> extN.patchT; \
- test $$? -le 1 || exit 1;
- done
- l='$(EXTNI)'; for f in $$l; do \
- echo "$$f"; \
- (diff -u $(extN_include_orig)/$$f $(top_srcdir)/include/linux/$$f)>>extN.patchT;\
- test $$? -le 1 || exit 1;
- done
- l='$(EXTN_EXTRA)'; for f in $$l; do \
- f=`echo "$$f" | sed 's%^fs/%%'`; \
- echo "$$f"; \
- (cd $(top_srcdir) && \
- diff -u /dev/null $$f) >> extN.patchT; \
- test $$? -le 1 || exit 1;
- done
- mv -f extN.patchT $(top_builddir)/$(subdir)/extN.patch-$(RELEASE)
- echo "Don't forget to add $(srcdir)/extN.patch-$(RELEASE) to CVS!"
-
-
-
-.PHONY: diff
-
-# Just do the SUB transformation on all our source files.
-
-
-sed-stamp:
- $(RM) $@
- rm -rf $(extN_orig) $(extN_include_orig)
- mkdir $(extN_orig) $(extN_include_orig)
- list='$(EXTNC)'; for f in $$list; do \
- echo "creating $(extN_orig)/$$f"; \
- sed $(SUB) $(LINUX)/fs/ext3/$$f > $(extN_orig)/$$f; \
- done
- list='$(EXTNI)'; for i in $$list; do \
- s=`echo $$i | sed "s/extN/ext3/"`; \
- echo "creating $(extN_include_orig)/$$i"; \
- sed $(SUB) $(LINUX)/include/linux/$$s > $(extN_include_orig)/$$i; \
- done
- echo timestamp > $@
-
-
-# Patch the kernel files with our ext3 patches. We need to go through some
-# extra hoops because the include files are in a different tree and because
-# patch likes to make local copies of files with (sym)links when it is patching
-# them. To avoid this, we copy/patch in the source dir instead of the build
-# dir (if they are different).
-# We also want to preserve the pristine transformed files for the diff target.
-
-
-
-patch-stamp: sed-stamp $(EXTNP)
- test -e $(top_builddir)/include/linux || mkdir -p $(top_builddir)/include/linux
- cp -a $(extN_orig)/* $(top_builddir)/$(subdir)
- cp -a $(extN_include_orig)/* $(top_builddir)/include/linux
- test -e $(top_builddir)/fs || ln -s . $(top_builddir)/fs
- list='$(EXTN_EXTRA)'; for f in $$list; do $(RM) $(top_builddir)/$$f; done
- if [ -f $(srcdir)/extN.patch-$(RELEASE) ]; then \
- echo "applying patch $(srcdir)/extN.patch-$(RELEASE)"; \
- (cd $(top_builddir) && patch -p0) < $(srcdir)/extN.patch-$(RELEASE); \
- else \
- echo "If first patch fails, read NOTE in extN/Makefile.am"; \
- list='$(EXTNP)'; \
- sed '/i_version/q' $(extN_orig)/namei.c | tail -2 | \
- grep extN_mark_inode_dirty >/dev/null && list="$(EXTN_FIXES) $$list"; \
- for p in $$list; do \
- echo "applying patch $$p"; \
- sed $(SUB) $(srcdir)/$$p | \
- (cd $(top_builddir) && patch -p1) || exit $$?; \
- done; \
- echo "It is OK if the next patch says it is already applied"; \
- echo "applying patch $(srcdir)/extN-2.4.18-exports.diff"; \
- (cd $(top_builddir) && \
- patch -N -p1) < $(srcdir)/extN-2.4.18-exports.diff; \
- echo "applying patch $(srcdir)/extN-2.4.18-ino_sb_fix.diff"; \
- (cd $(top_builddir) && \
- patch -p1) < $(srcdir)/extN-2.4.18-ino_sb_fixup.diff || exit $$?; \
- fi
- echo timestamp > $@
-
-
-
-
-$(extN_SOURCES) $(EXTNI) $(EXTN_EXTRA): patch-stamp
-
-# Don't distribute any patched files.
-dist-hook:
- $(RM) $(top_srcdir)/fs
- list='$(EXTNC)'; for f in $$list; do $(RM) $(distdir)/$$f; done
- list='$(EXTNI)'; for i in $$list; do \
- $(RM) $(distdir)/../include/linux/$$i; \
- done
- list='$(EXTN_EXTRA)'; for f in $$list; do $(RM) $(distdir)/../$$f; done
+++ /dev/null
-diff -ru lum-2.4.18-um30/fs/ext3/balloc.c uml-2.4.18-12.5/fs/ext3/balloc.c
---- lum-2.4.18-um30/fs/ext3/balloc.c Mon Feb 25 12:38:08 2002
-+++ uml-2.4.18-12.5/fs/ext3/balloc.c Thu Sep 19 13:40:11 2002
-@@ -276,7 +276,8 @@
- }
- lock_super (sb);
- es = sb->u.ext3_sb.s_es;
-- if (block < le32_to_cpu(es->s_first_data_block) ||
-+ if (block < le32_to_cpu(es->s_first_data_block) ||
-+ block + count < block ||
- (block + count) > le32_to_cpu(es->s_blocks_count)) {
- ext3_error (sb, "ext3_free_blocks",
- "Freeing blocks not in datazone - "
-@@ -309,17 +310,6 @@
- if (!gdp)
- goto error_return;
-
-- if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
-- in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
-- in_range (block, le32_to_cpu(gdp->bg_inode_table),
-- sb->u.ext3_sb.s_itb_per_group) ||
-- in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
-- sb->u.ext3_sb.s_itb_per_group))
-- ext3_error (sb, "ext3_free_blocks",
-- "Freeing blocks in system zones - "
-- "Block = %lu, count = %lu",
-- block, count);
--
- /*
- * We are about to start releasing blocks in the bitmap,
- * so we need undo access.
-@@ -345,14 +335,24 @@
- if (err)
- goto error_return;
-
-- for (i = 0; i < count; i++) {
-+ for (i = 0; i < count; i++, block++) {
-+ if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
-+ block == le32_to_cpu(gdp->bg_inode_bitmap) ||
-+ in_range(block, le32_to_cpu(gdp->bg_inode_table),
-+ sb->u.ext2_sb.s_itb_per_group)) {
-+ ext3_error(sb, __FUNCTION__,
-+ "Freeing block in system zone - block = %lu",
-+ block);
-+ continue;
-+ }
-+
- /*
- * An HJ special. This is expensive...
- */
- #ifdef CONFIG_JBD_DEBUG
- {
- struct buffer_head *debug_bh;
-- debug_bh = sb_get_hash_table(sb, block + i);
-+ debug_bh = sb_get_hash_table(sb, block);
- if (debug_bh) {
- BUFFER_TRACE(debug_bh, "Deleted!");
- if (!bh2jh(bitmap_bh)->b_committed_data)
-@@ -365,9 +365,8 @@
- #endif
- BUFFER_TRACE(bitmap_bh, "clear bit");
- if (!ext3_clear_bit (bit + i, bitmap_bh->b_data)) {
-- ext3_error (sb, __FUNCTION__,
-- "bit already cleared for block %lu",
-- block + i);
-+ ext3_error(sb, __FUNCTION__,
-+ "bit already cleared for block %lu", block);
- BUFFER_TRACE(bitmap_bh, "bit already cleared");
- } else {
- dquot_freed_blocks++;
-@@ -415,7 +417,6 @@
- if (!err) err = ret;
-
- if (overflow && !err) {
-- block += count;
- count = overflow;
- goto do_more;
- }
-@@ -542,6 +543,7 @@
- int i, j, k, tmp, alloctmp;
- int bitmap_nr;
- int fatal = 0, err;
-+ int performed_allocation = 0;
- struct super_block * sb;
- struct ext3_group_desc * gdp;
- struct ext3_super_block * es;
-@@ -575,6 +577,7 @@
-
- ext3_debug ("goal=%lu.\n", goal);
-
-+repeat:
- /*
- * First, test whether the goal block is free.
- */
-@@ -644,8 +647,7 @@
- }
-
- /* No space left on the device */
-- unlock_super (sb);
-- return 0;
-+ goto out;
-
- search_back:
- /*
-@@ -684,16 +686,28 @@
- if (tmp == le32_to_cpu(gdp->bg_block_bitmap) ||
- tmp == le32_to_cpu(gdp->bg_inode_bitmap) ||
- in_range (tmp, le32_to_cpu(gdp->bg_inode_table),
-- sb->u.ext3_sb.s_itb_per_group))
-- ext3_error (sb, "ext3_new_block",
-- "Allocating block in system zone - "
-- "block = %u", tmp);
-+ EXT3_SB(sb)->s_itb_per_group)) {
-+ ext3_error(sb, __FUNCTION__,
-+ "Allocating block in system zone - block = %u", tmp);
-+
-+ /* Note: This will potentially use up one of the handle's
-+ * buffer credits. Normally we have way too many credits,
-+ * so that is OK. In _very_ rare cases it might not be OK.
-+ * We will trigger an assertion if we run out of credits,
-+ * and we will have to do a full fsck of the filesystem -
-+ * better than randomly corrupting filesystem metadata.
-+ */
-+ ext3_set_bit(j, bh->b_data);
-+ goto repeat;
-+ }
-+
-
- /* The superblock lock should guard against anybody else beating
- * us to this point! */
- J_ASSERT_BH(bh, !ext3_test_bit(j, bh->b_data));
- BUFFER_TRACE(bh, "setting bitmap bit");
- ext3_set_bit(j, bh->b_data);
-+ performed_allocation = 1;
-
- #ifdef CONFIG_JBD_DEBUG
- {
-@@ -815,6 +829,11 @@
- ext3_std_error(sb, fatal);
- }
- unlock_super (sb);
-+ /*
-+ * Undo the block allocation
-+ */
-+ if (!performed_allocation)
-+ DQUOT_FREE_BLOCK(inode, 1);
- return 0;
-
- }
-diff -ru lum-2.4.18-um30/fs/ext3/file.c uml-2.4.18-12.5/fs/ext3/file.c
---- lum-2.4.18-um30/fs/ext3/file.c Thu Nov 15 14:37:55 2001
-+++ uml-2.4.18-12.5/fs/ext3/file.c Thu Sep 19 13:40:11 2002
-@@ -61,19 +61,52 @@
- static ssize_t
- ext3_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
- {
-+ int ret, err;
- struct inode *inode = file->f_dentry->d_inode;
-
-- /*
-- * Nasty: if the file is subject to synchronous writes then we need
-- * to force generic_osync_inode() to call ext3_write_inode().
-- * We do that by marking the inode dirty. This adds much more
-- * computational expense than we need, but we're going to sync
-- * anyway.
-- */
-- if (IS_SYNC(inode) || (file->f_flags & O_SYNC))
-- mark_inode_dirty(inode);
-+ ret = generic_file_write(file, buf, count, ppos);
-
-- return generic_file_write(file, buf, count, ppos);
-+ /* Skip file flushing code if there was an error, or if nothing
-+ was written. */
-+ if (ret <= 0)
-+ return ret;
-+
-+ /* If the inode is IS_SYNC, or is O_SYNC and we are doing
-+ data-journaling, then we need to make sure that we force the
-+ transaction to disk to keep all metadata uptodate
-+ synchronously. */
-+
-+ if (file->f_flags & O_SYNC) {
-+ /* If we are non-data-journaled, then the dirty data has
-+ already been flushed to backing store by
-+ generic_osync_inode, and the inode has been flushed
-+ too if there have been any modifications other than
-+ mere timestamp updates.
-+
-+ Open question --- do we care about flushing
-+ timestamps too if the inode is IS_SYNC? */
-+ if (!ext3_should_journal_data(inode))
-+ return ret;
-+
-+ goto force_commit;
-+ }
-+
-+ /* So we know that there has been no forced data flush. If the
-+ inode is marked IS_SYNC, we need to force one ourselves. */
-+ if (!IS_SYNC(inode))
-+ return ret;
-+
-+ /* Open question #2 --- should we force data to disk here too?
-+ If we don't, the only impact is that data=writeback
-+ filesystems won't flush data to disk automatically on
-+ IS_SYNC, only metadata (but historically, that is what ext2
-+ has done.) */
-+
-+force_commit:
-+ err = ext3_force_commit(inode->i_sb);
-+ if (err)
-+ return err;
-+ return ret;
- }
-
- struct file_operations ext3_file_operations = {
-diff -ru lum-2.4.18-um30/fs/ext3/fsync.c uml-2.4.18-12.5/fs/ext3/fsync.c
---- lum-2.4.18-um30/fs/ext3/fsync.c Tue Nov 20 22:34:13 2001
-+++ uml-2.4.18-12.5/fs/ext3/fsync.c Thu Sep 19 13:40:11 2002
-@@ -62,7 +62,12 @@
- * we'll end up waiting on them in commit.
- */
- ret = fsync_inode_buffers(inode);
-- ret |= fsync_inode_data_buffers(inode);
-+
-+ /* In writeback mode, we need to force out data buffers too. In
-+ * the other modes, ext3_force_commit takes care of forcing out
-+ * just the right data blocks. */
-+ if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
-+ ret |= fsync_inode_data_buffers(inode);
-
- ext3_force_commit(inode->i_sb);
-
-diff -ru lum-2.4.18-um30/fs/ext3/ialloc.c uml-2.4.18-12.5/fs/ext3/ialloc.c
---- lum-2.4.18-um30/fs/ext3/ialloc.c Mon Feb 25 12:38:08 2002
-+++ uml-2.4.18-12.5/fs/ext3/ialloc.c Thu Sep 19 13:40:11 2002
-@@ -392,7 +392,7 @@
-
- err = -ENOSPC;
- if (!gdp)
-- goto fail;
-+ goto out;
-
- err = -EIO;
- bitmap_nr = load_inode_bitmap (sb, i);
-@@ -523,9 +523,10 @@
- return inode;
-
- fail:
-+ ext3_std_error(sb, err);
-+out:
- unlock_super(sb);
- iput(inode);
-- ext3_std_error(sb, err);
- return ERR_PTR(err);
- }
-
-diff -ru lum-2.4.18-um30/fs/ext3/inode.c uml-2.4.18-12.5/fs/ext3/inode.c
---- lum-2.4.18-um30/fs/ext3/inode.c Mon Feb 25 12:38:08 2002
-+++ uml-2.4.18-12.5/fs/ext3/inode.c Thu Sep 19 13:40:11 2002
-@@ -412,6 +412,7 @@
- return NULL;
-
- changed:
-+ brelse(bh);
- *err = -EAGAIN;
- goto no_block;
- failure:
-@@ -581,8 +582,6 @@
-
- parent = nr;
- }
-- if (IS_SYNC(inode))
-- handle->h_sync = 1;
- }
- if (n == num)
- return 0;
-@@ -1015,8 +1018,8 @@
- unsigned from, unsigned to)
- {
- struct inode *inode = page->mapping->host;
-- handle_t *handle = ext3_journal_current_handle();
- int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
-+ handle_t *handle;
-
- lock_kernel();
- handle = ext3_journal_start(inode, needed_blocks);
-diff -ru lum-2.4.18-um30/fs/ext3/namei.c uml-2.4.18-12.5/fs/ext3/namei.c
---- lum-2.4.18-um30/fs/ext3/namei.c Fri Nov 9 15:25:04 2001
-+++ uml-2.4.18-12.5/fs/ext3/namei.c Thu Sep 19 13:40:11 2002
-@@ -354,8 +355,8 @@
- */
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-- ext3_mark_inode_dirty(handle, dir);
- dir->i_version = ++event;
-+ ext3_mark_inode_dirty(handle, dir);
- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, bh);
- brelse(bh);
-@@ -464,8 +465,8 @@
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
- inode->i_mapping->a_ops = &ext3_aops;
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -489,8 +490,8 @@
- err = PTR_ERR(inode);
- if (!IS_ERR(inode)) {
- init_special_inode(inode, mode, rdev);
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -933,8 +934,8 @@
- inode->i_size = l-1;
- }
- inode->u.ext3_i.i_disksize = inode->i_size;
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- out_stop:
- ext3_journal_stop(handle, dir);
- return err;
-@@ -970,8 +971,8 @@
- ext3_inc_count(handle, inode);
- atomic_inc(&inode->i_count);
-
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- ext3_journal_stop(handle, dir);
- return err;
- }
-diff -ru lum-2.4.18-um30/fs/ext3/super.c uml-2.4.18-12.5/fs/ext3/super.c
---- lum-2.4.18-um30/fs/ext3/super.c Fri Jul 12 17:59:37 2002
-+++ uml-2.4.18-12.5/fs/ext3/super.c Thu Sep 19 13:40:11 2002
-@@ -1589,8 +1589,10 @@
- journal_t *journal = EXT3_SB(sb)->s_journal;
-
- /* Now we set up the journal barrier. */
-+ unlock_super(sb);
- journal_lock_updates(journal);
- journal_flush(journal);
-+ lock_super(sb);
-
- /* Journal blocked and flushed, clear needs_recovery flag. */
- EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
+++ /dev/null
---- ./fs/ext3/balloc.c.orig Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/balloc.c Tue May 7 15:35:59 2002
-@@ -46,18 +46,18 @@ struct ext3_group_desc * ext3_get_group_
- unsigned long desc;
- struct ext3_group_desc * gdp;
-
-- if (block_group >= sb->u.ext3_sb.s_groups_count) {
-+ if (block_group >= EXT3_SB(sb)->s_groups_count) {
- ext3_error (sb, "ext3_get_group_desc",
- "block_group >= groups_count - "
- "block_group = %d, groups_count = %lu",
-- block_group, sb->u.ext3_sb.s_groups_count);
-+ block_group, EXT3_SB(sb)->s_groups_count);
-
- return NULL;
- }
-
- group_desc = block_group / EXT3_DESC_PER_BLOCK(sb);
- desc = block_group % EXT3_DESC_PER_BLOCK(sb);
-- if (!sb->u.ext3_sb.s_group_desc[group_desc]) {
-+ if (!EXT3_SB(sb)->s_group_desc[group_desc]) {
- ext3_error (sb, "ext3_get_group_desc",
- "Group descriptor not loaded - "
- "block_group = %d, group_desc = %lu, desc = %lu",
-@@ -66,9 +66,9 @@ struct ext3_group_desc * ext3_get_group_
- }
-
- gdp = (struct ext3_group_desc *)
-- sb->u.ext3_sb.s_group_desc[group_desc]->b_data;
-+ EXT3_SB(sb)->s_group_desc[group_desc]->b_data;
- if (bh)
-- *bh = sb->u.ext3_sb.s_group_desc[group_desc];
-+ *bh = EXT3_SB(sb)->s_group_desc[group_desc];
- return gdp + desc;
- }
-
-@@ -104,8 +104,8 @@ static int read_block_bitmap (struct sup
- * this group. The IO will be retried next time.
- */
- error_out:
-- sb->u.ext3_sb.s_block_bitmap_number[bitmap_nr] = block_group;
-- sb->u.ext3_sb.s_block_bitmap[bitmap_nr] = bh;
-+ EXT3_SB(sb)->s_block_bitmap_number[bitmap_nr] = block_group;
-+ EXT3_SB(sb)->s_block_bitmap[bitmap_nr] = bh;
- return retval;
- }
-
-@@ -128,16 +128,17 @@ static int __load_block_bitmap (struct s
- int i, j, retval = 0;
- unsigned long block_bitmap_number;
- struct buffer_head * block_bitmap;
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-
-- if (block_group >= sb->u.ext3_sb.s_groups_count)
-+ if (block_group >= sbi->s_groups_count)
- ext3_panic (sb, "load_block_bitmap",
- "block_group >= groups_count - "
- "block_group = %d, groups_count = %lu",
-- block_group, sb->u.ext3_sb.s_groups_count);
-+ block_group, EXT3_SB(sb)->s_groups_count);
-
-- if (sb->u.ext3_sb.s_groups_count <= EXT3_MAX_GROUP_LOADED) {
-- if (sb->u.ext3_sb.s_block_bitmap[block_group]) {
-- if (sb->u.ext3_sb.s_block_bitmap_number[block_group] ==
-+ if (sbi->s_groups_count <= EXT3_MAX_GROUP_LOADED) {
-+ if (sbi->s_block_bitmap[block_group]) {
-+ if (sbi->s_block_bitmap_number[block_group] ==
- block_group)
- return block_group;
- ext3_error (sb, "__load_block_bitmap",
-@@ -149,21 +150,20 @@ static int __load_block_bitmap (struct s
- return block_group;
- }
-
-- for (i = 0; i < sb->u.ext3_sb.s_loaded_block_bitmaps &&
-- sb->u.ext3_sb.s_block_bitmap_number[i] != block_group; i++)
-+ for (i = 0; i < sbi->s_loaded_block_bitmaps &&
-+ sbi->s_block_bitmap_number[i] != block_group; i++)
- ;
-- if (i < sb->u.ext3_sb.s_loaded_block_bitmaps &&
-- sb->u.ext3_sb.s_block_bitmap_number[i] == block_group) {
-- block_bitmap_number = sb->u.ext3_sb.s_block_bitmap_number[i];
-- block_bitmap = sb->u.ext3_sb.s_block_bitmap[i];
-+ if (i < sbi->s_loaded_block_bitmaps &&
-+ sbi->s_block_bitmap_number[i] == block_group) {
-+ block_bitmap_number = sbi->s_block_bitmap_number[i];
-+ block_bitmap = sbi->s_block_bitmap[i];
- for (j = i; j > 0; j--) {
-- sb->u.ext3_sb.s_block_bitmap_number[j] =
-- sb->u.ext3_sb.s_block_bitmap_number[j - 1];
-- sb->u.ext3_sb.s_block_bitmap[j] =
-- sb->u.ext3_sb.s_block_bitmap[j - 1];
-+ sbi->s_block_bitmap_number[j] =
-+ sbi->s_block_bitmap_number[j - 1];
-+ sbi->s_block_bitmap[j] = sbi->s_block_bitmap[j - 1];
- }
-- sb->u.ext3_sb.s_block_bitmap_number[0] = block_bitmap_number;
-- sb->u.ext3_sb.s_block_bitmap[0] = block_bitmap;
-+ sbi->s_block_bitmap_number[0] = block_bitmap_number;
-+ sbi->s_block_bitmap[0] = block_bitmap;
-
- /*
- * There's still one special case here --- if block_bitmap == 0
-@@ -173,17 +173,14 @@ static int __load_block_bitmap (struct s
- if (!block_bitmap)
- retval = read_block_bitmap (sb, block_group, 0);
- } else {
-- if (sb->u.ext3_sb.s_loaded_block_bitmaps<EXT3_MAX_GROUP_LOADED)
-- sb->u.ext3_sb.s_loaded_block_bitmaps++;
-+ if (sbi->s_loaded_block_bitmaps<EXT3_MAX_GROUP_LOADED)
-+ sbi->s_loaded_block_bitmaps++;
- else
-- brelse (sb->u.ext3_sb.s_block_bitmap
-- [EXT3_MAX_GROUP_LOADED - 1]);
-- for (j = sb->u.ext3_sb.s_loaded_block_bitmaps - 1;
-- j > 0; j--) {
-- sb->u.ext3_sb.s_block_bitmap_number[j] =
-- sb->u.ext3_sb.s_block_bitmap_number[j - 1];
-- sb->u.ext3_sb.s_block_bitmap[j] =
-- sb->u.ext3_sb.s_block_bitmap[j - 1];
-+ brelse(sbi->s_block_bitmap[EXT3_MAX_GROUP_LOADED - 1]);
-+ for (j = sbi->s_loaded_block_bitmaps - 1; j > 0; j--) {
-+ sbi->s_block_bitmap_number[j] =
-+ sbi->s_block_bitmap_number[j - 1];
-+ sbi->s_block_bitmap[j] = sbi->s_block_bitmap[j - 1];
- }
- retval = read_block_bitmap (sb, block_group, 0);
- }
-@@ -206,24 +203,25 @@ static int __load_block_bitmap (struct s
- static inline int load_block_bitmap (struct super_block * sb,
- unsigned int block_group)
- {
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
- int slot;
--
-+
- /*
- * Do the lookup for the slot. First of all, check if we're asking
- * for the same slot as last time, and did we succeed that last time?
- */
-- if (sb->u.ext3_sb.s_loaded_block_bitmaps > 0 &&
-- sb->u.ext3_sb.s_block_bitmap_number[0] == block_group &&
-- sb->u.ext3_sb.s_block_bitmap[0]) {
-+ if (sbi->s_loaded_block_bitmaps > 0 &&
-+ sbi->s_block_bitmap_number[0] == block_group &&
-+ sbi->s_block_bitmap[0]) {
- return 0;
- }
- /*
- * Or can we do a fast lookup based on a loaded group on a filesystem
- * small enough to be mapped directly into the superblock?
- */
-- else if (sb->u.ext3_sb.s_groups_count <= EXT3_MAX_GROUP_LOADED &&
-- sb->u.ext3_sb.s_block_bitmap_number[block_group]==block_group
-- && sb->u.ext3_sb.s_block_bitmap[block_group]) {
-+ else if (sbi->s_groups_count <= EXT3_MAX_GROUP_LOADED &&
-+ sbi->s_block_bitmap_number[block_group] == block_group
-+ && sbi->s_block_bitmap[block_group]) {
- slot = block_group;
- }
- /*
-@@ -243,7 +241,7 @@ static inline int load_block_bitmap (str
- * If it's a valid slot, we may still have cached a previous IO error,
- * in which case the bh in the superblock cache will be zero.
- */
-- if (!sb->u.ext3_sb.s_block_bitmap[slot])
-+ if (!sbi->s_block_bitmap[slot])
- return -EIO;
-
- /*
-@@ -275,7 +273,7 @@ void ext3_free_blocks (handle_t *handle,
- return;
- }
- lock_super (sb);
-- es = sb->u.ext3_sb.s_es;
-+ es = EXT3_SB(sb)->s_es;
- if (block < le32_to_cpu(es->s_first_data_block) ||
- block + count < block ||
- (block + count) > le32_to_cpu(es->s_blocks_count)) {
-@@ -304,7 +302,7 @@ do_more:
- if (bitmap_nr < 0)
- goto error_return;
-
-- bitmap_bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
-+ bitmap_bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
- gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
- if (!gdp)
- goto error_return;
-@@ -330,8 +328,8 @@ do_more:
- if (err)
- goto error_return;
-
-- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
-- err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
- if (err)
- goto error_return;
-
-@@ -341,7 +339,7 @@
- if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
- block == le32_to_cpu(gdp->bg_inode_bitmap) ||
- in_range(block, le32_to_cpu(gdp->bg_inode_table),
-- sb->u.ext2_sb.s_itb_per_group)) {
-+ EXT3_SB(sb)->s_itb_per_group)) {
- ext3_error(sb, __FUNCTION__,
- "Freeing block in system zone - block = %lu",
- block);
-@@ -410,8 +407,8 @@ do_more:
- if (!err) err = ret;
-
- /* And the superblock */
-- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "dirtied superblock");
-- ret = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "dirtied superblock");
-+ ret = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
- if (!err) err = ret;
-
- if (overflow && !err) {
-@@ -564,12 +560,12 @@ int ext3_new_block (handle_t *handle, st
- }
-
- lock_super (sb);
-- es = sb->u.ext3_sb.s_es;
-+ es = EXT3_SB(sb)->s_es;
- if (le32_to_cpu(es->s_free_blocks_count) <=
- le32_to_cpu(es->s_r_blocks_count) &&
-- ((sb->u.ext3_sb.s_resuid != current->fsuid) &&
-- (sb->u.ext3_sb.s_resgid == 0 ||
-- !in_group_p (sb->u.ext3_sb.s_resgid)) &&
-+ ((EXT3_SB(sb)->s_resuid != current->fsuid) &&
-+ (EXT3_SB(sb)->s_resgid == 0 ||
-+ !in_group_p (EXT3_SB(sb)->s_resgid)) &&
- !capable(CAP_SYS_RESOURCE)))
- goto out;
-
-@@ -598,7 +595,7 @@ int ext3_new_block (handle_t *handle, st
- if (bitmap_nr < 0)
- goto io_error;
-
-- bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
-+ bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
-
- ext3_debug ("goal is at %d:%d.\n", i, j);
-
-@@ -621,9 +618,9 @@ int ext3_new_block (handle_t *handle, st
- * Now search the rest of the groups. We assume that
- * i and gdp correctly point to the last group visited.
- */
-- for (k = 0; k < sb->u.ext3_sb.s_groups_count; k++) {
-+ for (k = 0; k < EXT3_SB(sb)->s_groups_count; k++) {
- i++;
-- if (i >= sb->u.ext3_sb.s_groups_count)
-+ if (i >= EXT3_SB(sb)->s_groups_count)
- i = 0;
- gdp = ext3_get_group_desc (sb, i, &bh2);
- if (!gdp) {
-@@ -635,7 +632,7 @@ int ext3_new_block (handle_t *handle, st
- if (bitmap_nr < 0)
- goto io_error;
-
-- bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];
-+ bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];
- j = find_next_usable_block(-1, bh,
- EXT3_BLOCKS_PER_GROUP(sb));
- if (j >= 0)
-@@ -674,8 +671,8 @@ got_block:
- fatal = ext3_journal_get_write_access(handle, bh2);
- if (fatal) goto out;
-
-- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
-- fatal = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access");
-+ fatal = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
- if (fatal) goto out;
-
- tmp = j + i * EXT3_BLOCKS_PER_GROUP(sb)
-@@ -796,7 +804,7 @@ got_block:
- if (!fatal) fatal = err;
-
- BUFFER_TRACE(bh, "journal_dirty_metadata for superblock");
-- err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
- if (!fatal) fatal = err;
-
- sb->s_dirt = 1;
-@@ -829,11 +837,11 @@ unsigned long ext3_count_free_blocks (st
- int i;
-
- lock_super (sb);
-- es = sb->u.ext3_sb.s_es;
-+ es = EXT3_SB(sb)->s_es;
- desc_count = 0;
- bitmap_count = 0;
- gdp = NULL;
-- for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+ for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
- gdp = ext3_get_group_desc (sb, i, NULL);
- if (!gdp)
- continue;
-@@ -842,7 +850,7 @@ unsigned long ext3_count_free_blocks (st
- if (bitmap_nr < 0)
- continue;
-
-- x = ext3_count_free (sb->u.ext3_sb.s_block_bitmap[bitmap_nr],
-+ x = ext3_count_free (EXT3_SB(sb)->s_block_bitmap[bitmap_nr],
- sb->s_blocksize);
- printk ("group %d: stored = %d, counted = %lu\n",
- i, le16_to_cpu(gdp->bg_free_blocks_count), x);
-@@ -853,7 +861,7 @@ unsigned long ext3_count_free_blocks (st
- unlock_super (sb);
- return bitmap_count;
- #else
-- return le32_to_cpu(sb->u.ext3_sb.s_es->s_free_blocks_count);
-+ return le32_to_cpu(EXT3_SB(sb)->s_es->s_free_blocks_count);
- #endif
- }
-
-@@ -862,7 +870,7 @@ static inline int block_in_use (unsigned
- unsigned char * map)
- {
- return ext3_test_bit ((block -
-- le32_to_cpu(sb->u.ext3_sb.s_es->s_first_data_block)) %
-+ le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) %
- EXT3_BLOCKS_PER_GROUP(sb), map);
- }
-
-@@ -930,11 +938,11 @@ void ext3_check_blocks_bitmap (struct su
- struct ext3_group_desc * gdp;
- int i;
-
-- es = sb->u.ext3_sb.s_es;
-+ es = EXT3_SB(sb)->s_es;
- desc_count = 0;
- bitmap_count = 0;
- gdp = NULL;
-- for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+ for (i = 0; i < EXT3_SB(sb)->s_groups_count; i++) {
- gdp = ext3_get_group_desc (sb, i, NULL);
- if (!gdp)
- continue;
-@@ -968,7 +976,7 @@ void ext3_check_blocks_bitmap (struct su
- "Inode bitmap for group %d is marked free",
- i);
-
-- for (j = 0; j < sb->u.ext3_sb.s_itb_per_group; j++)
-+ for (j = 0; j < EXT3_SB(sb)->s_itb_per_group; j++)
- if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j,
- sb, bh->b_data))
- ext3_error (sb, "ext3_check_blocks_bitmap",
---- ./fs/ext3/dir.c.orig Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/dir.c Tue May 7 14:54:13 2002
-@@ -52,7 +52,7 @@ int ext3_check_dir_entry (const char * f
- else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
- error_msg = "directory entry across blocks";
- else if (le32_to_cpu(de->inode) >
-- le32_to_cpu(dir->i_sb->u.ext3_sb.s_es->s_inodes_count))
-+ le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))
- error_msg = "inode out of bounds";
-
- if (error_msg != NULL)
---- ./fs/ext3/ialloc.c.orig Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/ialloc.c Tue May 7 15:39:26 2002
-@@ -73,8 +73,8 @@ static int read_inode_bitmap (struct sup
- * this group. The IO will be retried next time.
- */
- error_out:
-- sb->u.ext3_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
-- sb->u.ext3_sb.s_inode_bitmap[bitmap_nr] = bh;
-+ EXT3_SB(sb)->s_inode_bitmap_number[bitmap_nr] = block_group;
-+ EXT3_SB(sb)->s_inode_bitmap[bitmap_nr] = bh;
- return retval;
- }
-
-@@ -225,7 +225,7 @@ void ext3_free_inode (handle_t *handle,
- clear_inode (inode);
-
- lock_super (sb);
-- es = sb->u.ext3_sb.s_es;
-+ es = EXT3_SB(sb)->s_es;
- if (ino < EXT3_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
- ext3_error (sb, "ext3_free_inode",
- "reserved or nonexistent inode %lu", ino);
-@@ -237,7 +237,7 @@ void ext3_free_inode (handle_t *handle,
- if (bitmap_nr < 0)
- goto error_return;
-
-- bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
-+ bh = EXT3_SB(sb)->s_inode_bitmap[bitmap_nr];
-
- BUFFER_TRACE(bh, "get_write_access");
- fatal = ext3_journal_get_write_access(handle, bh);
-@@ -255,8 +255,8 @@ void ext3_free_inode (handle_t *handle,
- fatal = ext3_journal_get_write_access(handle, bh2);
- if (fatal) goto error_return;
-
-- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get write access");
-- fatal = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get write access");
-+ fatal = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
- if (fatal) goto error_return;
-
- if (gdp) {
-@@ -271,9 +271,9 @@ void ext3_free_inode (handle_t *handle,
- if (!fatal) fatal = err;
- es->s_free_inodes_count =
- cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
-- BUFFER_TRACE(sb->u.ext3_sb.s_sbh,
-+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh,
- "call ext3_journal_dirty_metadata");
-- err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
- if (!fatal) fatal = err;
- }
- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-@@ -305,6 +305,8 @@ struct inode * ext3_new_inode (handle_t
- int i, j, avefreei;
- struct inode * inode;
- int bitmap_nr;
-+ struct ext3_inode_info *ei;
-+ struct ext3_sb_info *sbi;
- struct ext3_group_desc * gdp;
- struct ext3_group_desc * tmp;
- struct ext3_super_block * es;
-@@ -318,19 +320,21 @@ struct inode * ext3_new_inode (handle_t
- inode = new_inode(sb);
- if (!inode)
- return ERR_PTR(-ENOMEM);
-- init_rwsem(&inode->u.ext3_i.truncate_sem);
-+ sbi = EXT3_SB(sb);
-+ ei = EXT3_I(inode);
-+ init_rwsem(&ei->truncate_sem);
-
- lock_super (sb);
-- es = sb->u.ext3_sb.s_es;
-+ es = sbi->s_es;
- repeat:
- gdp = NULL;
- i = 0;
-
- if (S_ISDIR(mode)) {
- avefreei = le32_to_cpu(es->s_free_inodes_count) /
-- sb->u.ext3_sb.s_groups_count;
-+ sbi->s_groups_count;
- if (!gdp) {
-- for (j = 0; j < sb->u.ext3_sb.s_groups_count; j++) {
-+ for (j = 0; j < sbi->s_groups_count; j++) {
- struct buffer_head *temp_buffer;
- tmp = ext3_get_group_desc (sb, j, &temp_buffer);
- if (tmp &&
-@@ -350,7 +354,7 @@ repeat:
- /*
- * Try to place the inode in its parent directory
- */
-- i = dir->u.ext3_i.i_block_group;
-+ i = EXT3_I(dir)->i_block_group;
- tmp = ext3_get_group_desc (sb, i, &bh2);
- if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
- gdp = tmp;
-@@ -360,10 +364,10 @@ repeat:
- * Use a quadratic hash to find a group with a
- * free inode
- */
-- for (j = 1; j < sb->u.ext3_sb.s_groups_count; j <<= 1) {
-+ for (j = 1; j < sbi->s_groups_count; j <<= 1) {
- i += j;
-- if (i >= sb->u.ext3_sb.s_groups_count)
-- i -= sb->u.ext3_sb.s_groups_count;
-+ if (i >= sbi->s_groups_count)
-+ i -= sbi->s_groups_count;
- tmp = ext3_get_group_desc (sb, i, &bh2);
- if (tmp &&
- le16_to_cpu(tmp->bg_free_inodes_count)) {
-@@ -376,9 +380,9 @@ repeat:
- /*
- * That failed: try linear search for a free inode
- */
-- i = dir->u.ext3_i.i_block_group + 1;
-- for (j = 2; j < sb->u.ext3_sb.s_groups_count; j++) {
-- if (++i >= sb->u.ext3_sb.s_groups_count)
-+ i = EXT3_I(dir)->i_block_group + 1;
-+ for (j = 2; j < sbi->s_groups_count; j++) {
-+ if (++i >= sbi->s_groups_count)
- i = 0;
- tmp = ext3_get_group_desc (sb, i, &bh2);
- if (tmp &&
-@@ -399,11 +403,11 @@ repeat:
- if (bitmap_nr < 0)
- goto fail;
-
-- bh = sb->u.ext3_sb.s_inode_bitmap[bitmap_nr];
-+ bh = sbi->s_inode_bitmap[bitmap_nr];
-
- if ((j = ext3_find_first_zero_bit ((unsigned long *) bh->b_data,
-- EXT3_INODES_PER_GROUP(sb))) <
-- EXT3_INODES_PER_GROUP(sb)) {
-+ sbi->s_inodes_per_group)) <
-+ sbi->s_inodes_per_group) {
- BUFFER_TRACE(bh, "get_write_access");
- err = ext3_journal_get_write_access(handle, bh);
- if (err) goto fail;
-@@ -436,8 +440,8 @@ repeat:
- }
- goto repeat;
- }
-- j += i * EXT3_INODES_PER_GROUP(sb) + 1;
-- if (j < EXT3_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) {
-+ j += i * sbi->s_inodes_per_group + 1;
-+ if (j < sbi->s_first_ino || j > le32_to_cpu(es->s_inodes_count)) {
- ext3_error (sb, "ext3_new_inode",
- "reserved inode or inode > inodes count - "
- "block_group = %d,inode=%d", i, j);
-@@ -457,13 +461,13 @@ repeat:
- err = ext3_journal_dirty_metadata(handle, bh2);
- if (err) goto fail;
-
-- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
-- err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+ BUFFER_TRACE(sbi->s_sbh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, sbi->s_sbh);
- if (err) goto fail;
- es->s_free_inodes_count =
- cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1);
-- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "call ext3_journal_dirty_metadata");
-- err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+ BUFFER_TRACE(sbi->s_sbh, "call ext3_journal_dirty_metadata");
-+ err = ext3_journal_dirty_metadata(handle, sbi->s_sbh);
- sb->s_dirt = 1;
- if (err) goto fail;
-
-@@ -483,31 +487,31 @@ repeat:
- inode->i_blksize = PAGE_SIZE;
- inode->i_blocks = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-- inode->u.ext3_i.i_flags = dir->u.ext3_i.i_flags & ~EXT3_INDEX_FL;
-+ ei->i_flags = EXT3_I(dir)->i_flags & ~EXT3_INDEX_FL;
- if (S_ISLNK(mode))
-- inode->u.ext3_i.i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
-+ ei->i_flags &= ~(EXT3_IMMUTABLE_FL|EXT3_APPEND_FL);
- #ifdef EXT3_FRAGMENTS
-- inode->u.ext3_i.i_faddr = 0;
-- inode->u.ext3_i.i_frag_no = 0;
-- inode->u.ext3_i.i_frag_size = 0;
-+ ei->i_faddr = 0;
-+ ei->i_frag_no = 0;
-+ ei->i_frag_size = 0;
- #endif
-- inode->u.ext3_i.i_file_acl = 0;
-- inode->u.ext3_i.i_dir_acl = 0;
-- inode->u.ext3_i.i_dtime = 0;
-- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+ ei->i_file_acl = 0;
-+ ei->i_dir_acl = 0;
-+ ei->i_dtime = 0;
-+ INIT_LIST_HEAD(&ei->i_orphan);
- #ifdef EXT3_PREALLOCATE
-- inode->u.ext3_i.i_prealloc_count = 0;
-+ ei->i_prealloc_count = 0;
- #endif
-- inode->u.ext3_i.i_block_group = i;
-+ ei->i_block_group = i;
-
-- if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL)
-+ if (ei->i_flags & EXT3_SYNC_FL)
- inode->i_flags |= S_SYNC;
- if (IS_SYNC(inode))
- handle->h_sync = 1;
- insert_inode_hash(inode);
-- inode->i_generation = sb->u.ext3_sb.s_next_generation++;
-+ inode->i_generation = sbi->s_next_generation++;
-
-- inode->u.ext3_i.i_state = EXT3_STATE_NEW;
-+ ei->i_state = EXT3_STATE_NEW;
- err = ext3_mark_inode_dirty(handle, inode);
- if (err) goto fail;
-
-@@ -585,19 +589,19 @@ struct inode *ext3_orphan_get (struct su
-
- unsigned long ext3_count_free_inodes (struct super_block * sb)
- {
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
-+ struct ext3_super_block *es = sbi->s_es;
- #ifdef EXT3FS_DEBUG
-- struct ext3_super_block * es;
- unsigned long desc_count, bitmap_count, x;
- int bitmap_nr;
- struct ext3_group_desc * gdp;
- int i;
-
- lock_super (sb);
-- es = sb->u.ext3_sb.s_es;
- desc_count = 0;
- bitmap_count = 0;
- gdp = NULL;
-- for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+ for (i = 0; i < sbi->s_groups_count; i++) {
- gdp = ext3_get_group_desc (sb, i, NULL);
- if (!gdp)
- continue;
-@@ -606,8 +610,8 @@ unsigned long ext3_count_free_inodes (st
- if (bitmap_nr < 0)
- continue;
-
-- x = ext3_count_free (sb->u.ext3_sb.s_inode_bitmap[bitmap_nr],
-- EXT3_INODES_PER_GROUP(sb) / 8);
-+ x = ext3_count_free(sbi->s_inode_bitmap[bitmap_nr],
-+ sbi->s_inodes_per_group / 8);
- printk ("group %d: stored = %d, counted = %lu\n",
- i, le16_to_cpu(gdp->bg_free_inodes_count), x);
- bitmap_count += x;
-@@ -617,7 +621,7 @@ unsigned long ext3_count_free_inodes (st
- unlock_super (sb);
- return desc_count;
- #else
-- return le32_to_cpu(sb->u.ext3_sb.s_es->s_free_inodes_count);
-+ return le32_to_cpu(es->s_free_inodes_count);
- #endif
- }
-
-@@ -626,16 +630,18 @@ unsigned long ext3_count_free_inodes (st
- void ext3_check_inodes_bitmap (struct super_block * sb)
- {
- struct ext3_super_block * es;
-+ struct ext3_sb_info *sbi;
- unsigned long desc_count, bitmap_count, x;
- int bitmap_nr;
- struct ext3_group_desc * gdp;
- int i;
-
-- es = sb->u.ext3_sb.s_es;
-+ sbi = EXT3_SB(sb);
-+ es = sbi->s_es;
- desc_count = 0;
- bitmap_count = 0;
- gdp = NULL;
-- for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {
-+ for (i = 0; i < sbi->s_groups_count; i++) {
- gdp = ext3_get_group_desc (sb, i, NULL);
- if (!gdp)
- continue;
-@@ -644,7 +650,7 @@ void ext3_check_inodes_bitmap (struct su
- if (bitmap_nr < 0)
- continue;
-
-- x = ext3_count_free (sb->u.ext3_sb.s_inode_bitmap[bitmap_nr],
-+ x = ext3_count_free (sbi->s_inode_bitmap[bitmap_nr],
- EXT3_INODES_PER_GROUP(sb) / 8);
- if (le16_to_cpu(gdp->bg_free_inodes_count) != x)
- ext3_error (sb, "ext3_check_inodes_bitmap",
---- ./fs/ext3/inode.c.orig Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/inode.c Tue May 7 15:41:23 2002
-@@ -196,7 +196,7 @@ void ext3_delete_inode (struct inode * i
- * (Well, we could do this if we need to, but heck - it works)
- */
- ext3_orphan_del(handle, inode);
-- inode->u.ext3_i.i_dtime = CURRENT_TIME;
-+ EXT3_I(inode)->i_dtime = CURRENT_TIME;
-
- /*
- * One subtle ordering requirement: if anything has gone wrong
-@@ -220,13 +220,14 @@ no_delete:
- void ext3_discard_prealloc (struct inode * inode)
- {
- #ifdef EXT3_PREALLOCATE
-+ struct ext3_inode_info *ei = EXT3_I(inode);
- lock_kernel();
- /* Writer: ->i_prealloc* */
-- if (inode->u.ext3_i.i_prealloc_count) {
-- unsigned short total = inode->u.ext3_i.i_prealloc_count;
-- unsigned long block = inode->u.ext3_i.i_prealloc_block;
-- inode->u.ext3_i.i_prealloc_count = 0;
-- inode->u.ext3_i.i_prealloc_block = 0;
-+ if (ei->i_prealloc_count) {
-+ unsigned short total = ei->i_prealloc_count;
-+ unsigned long block = ei->i_prealloc_block;
-+ ei->i_prealloc_count = 0;
-+ ei->i_prealloc_block = 0;
- /* Writer: end */
- ext3_free_blocks (inode, block, total);
- }
-@@ -243,13 +244,15 @@ static int ext3_alloc_block (handle_t *h
- unsigned long result;
-
- #ifdef EXT3_PREALLOCATE
-+ struct ext3_inode_info *ei = EXT3_I(inode);
-+
- /* Writer: ->i_prealloc* */
-- if (inode->u.ext3_i.i_prealloc_count &&
-- (goal == inode->u.ext3_i.i_prealloc_block ||
-- goal + 1 == inode->u.ext3_i.i_prealloc_block))
-+ if (ei->i_prealloc_count &&
-+ (goal == ei->i_prealloc_block ||
-+ goal + 1 == ei->i_prealloc_block))
- {
-- result = inode->u.ext3_i.i_prealloc_block++;
-- inode->u.ext3_i.i_prealloc_count--;
-+ result = ei->i_prealloc_block++;
-+ ei->i_prealloc_count--;
- /* Writer: end */
- ext3_debug ("preallocation hit (%lu/%lu).\n",
- ++alloc_hits, ++alloc_attempts);
-@@ -259,8 +262,8 @@ static int ext3_alloc_block (handle_t *h
- alloc_hits, ++alloc_attempts);
- if (S_ISREG(inode->i_mode))
- result = ext3_new_block (inode, goal,
-- &inode->u.ext3_i.i_prealloc_count,
-- &inode->u.ext3_i.i_prealloc_block, err);
-+ &ei->i_prealloc_count,
-+ &ei->i_prealloc_block, err);
- else
- result = ext3_new_block (inode, goal, 0, 0, err);
- /*
-@@ -394,7 +397,7 @@ static Indirect *ext3_get_branch(struct
-
- *err = 0;
- /* i_data is not going away, no lock needed */
-- add_chain (chain, NULL, inode->u.ext3_i.i_data + *offsets);
-+ add_chain (chain, NULL, EXT3_I(inode)->i_data + *offsets);
- if (!p->key)
- goto no_block;
- while (--depth) {
-@@ -437,7 +440,8 @@ no_block:
-
- static inline unsigned long ext3_find_near(struct inode *inode, Indirect *ind)
- {
-- u32 *start = ind->bh ? (u32*) ind->bh->b_data : inode->u.ext3_i.i_data;
-+ struct ext3_inode_info *ei = EXT3_I(inode);
-+ u32 *start = ind->bh ? (u32*) ind->bh->b_data : ei->i_data;
- u32 *p;
-
- /* Try to find previous block */
-@@ -453,9 +456,8 @@ static inline unsigned long ext3_find_ne
- * It is going to be refered from inode itself? OK, just put it into
- * the same cylinder group then.
- */
-- return (inode->u.ext3_i.i_block_group *
-- EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
-- le32_to_cpu(inode->i_sb->u.ext3_sb.s_es->s_first_data_block);
-+ return (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
-+ le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
- }
-
- /**
-@@ -474,14 +477,15 @@
- static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4],
- Indirect *partial, unsigned long *goal)
- {
-+ struct ext3_inode_info *ei = EXT3_I(inode);
- /* Writer: ->i_next_alloc* */
-- if (block == inode->u.ext3_i.i_next_alloc_block + 1) {
-- inode->u.ext3_i.i_next_alloc_block++;
-- inode->u.ext3_i.i_next_alloc_goal++;
-+ if (block == ei->i_next_alloc_block + 1) {
-+ ei->i_next_alloc_block++;
-+ ei->i_next_alloc_goal++;
- }
- #ifdef SEARCH_FROM_ZERO
-- inode->u.ext3_i.i_next_alloc_block = 0;
-- inode->u.ext3_i.i_next_alloc_goal = 0;
-+ ei->i_next_alloc_block = 0;
-+ ei->i_next_alloc_goal = 0;
- #endif
- /* Writer: end */
- /* Reader: pointers, ->i_next_alloc* */
-@@ -490,8 +493,8 @@ static int ext3_find_goal(struct inode *
- * try the heuristic for sequential allocation,
- * failing that at least try to get decent locality.
- */
-- if (block == inode->u.ext3_i.i_next_alloc_block)
-- *goal = inode->u.ext3_i.i_next_alloc_goal;
-+ if (block == ei->i_next_alloc_block)
-+ *goal = ei->i_next_alloc_goal;
- if (!*goal)
- *goal = ext3_find_near(inode, partial);
- #ifdef SEARCH_FROM_ZERO
-@@ -619,6 +621,7 @@
- {
- int i;
- int err = 0;
-+ struct ext3_inode_info *ei = EXT3_I(inode);
-
- /*
- * If we're splicing into a [td]indirect block (as opposed to the
-@@ -641,11 +644,11 @@ static int ext3_splice_branch(handle_t *
- /* That's it */
-
- *where->p = where->key;
-- inode->u.ext3_i.i_next_alloc_block = block;
-- inode->u.ext3_i.i_next_alloc_goal = le32_to_cpu(where[num-1].key);
-+ ei->i_next_alloc_block = block;
-+ ei->i_next_alloc_goal = le32_to_cpu(where[num-1].key);
- #ifdef SEARCH_FROM_ZERO
-- inode->u.ext3_i.i_next_alloc_block = 0;
-- inode->u.ext3_i.i_next_alloc_goal = 0;
-+ ei->i_next_alloc_block = 0;
-+ ei->i_next_alloc_goal = 0;
- #endif
- /* Writer: end */
-
-@@ -729,6 +732,7 @@
- unsigned long goal;
- int left;
- int depth = ext3_block_to_path(inode, iblock, offsets);
-+ struct ext3_inode_info *ei = EXT3_I(inode);
- loff_t new_size;
-
- J_ASSERT(handle != NULL || create == 0);
-@@ -782,7 +785,7 @@ out:
- /*
- * Block out ext3_truncate while we alter the tree
- */
-- down_read(&inode->u.ext3_i.truncate_sem);
-+ down_read(&ei->truncate_sem);
- err = ext3_alloc_branch(handle, inode, left, goal,
- offsets+(partial-chain), partial);
-
-@@ -794,7 +797,7 @@ out:
- if (!err)
- err = ext3_splice_branch(handle, inode, iblock, chain,
- partial, left);
-- up_read(&inode->u.ext3_i.truncate_sem);
-+ up_read(&ei->truncate_sem);
- if (err == -EAGAIN)
- goto changed;
- if (err)
-@@ -807,8 +810,8 @@ out:
- * truncate is in progress. It is racy between multiple parallel
- * instances of get_block, but we have the BKL.
- */
-- if (new_size > inode->u.ext3_i.i_disksize)
-- inode->u.ext3_i.i_disksize = new_size;
-+ if (new_size > ei->i_disksize)
-+ ei->i_disksize = new_size;
-
- bh_result->b_state |= (1UL << BH_New);
- goto got_it;
-@@ -921,7 +924,7 @@ struct buffer_head *ext3_bread(handle_t
- struct buffer_head *tmp_bh;
-
- for (i = 1;
-- inode->u.ext3_i.i_prealloc_count &&
-+ EXT3_I(inode)->i_prealloc_count &&
- i < EXT3_SB(inode->i_sb)->s_es->s_prealloc_dir_blocks;
- i++) {
- /*
-@@ -1131,8 +1134,8 @@ static int ext3_commit_write(struct file
- kunmap(page);
- }
- }
-- if (inode->i_size > inode->u.ext3_i.i_disksize) {
-- inode->u.ext3_i.i_disksize = inode->i_size;
-+ if (inode->i_size > EXT3_I(inode)->i_disksize) {
-+ EXT3_I(inode)->i_disksize = inode->i_size;
- ret2 = ext3_mark_inode_dirty(handle, inode);
- if (!ret)
- ret = ret2;
-@@ -1832,7 +1835,8 @@ static void ext3_free_branches(handle_t
- void ext3_truncate(struct inode * inode)
- {
- handle_t *handle;
-- u32 *i_data = inode->u.ext3_i.i_data;
-+ struct ext3_inode_info *ei = EXT3_I(inode);
-+ u32 *i_data = EXT3_I(inode)->i_data;
- int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb);
- int offsets[4];
- Indirect chain[4];
-@@ -1884,13 +1887,13 @@ void ext3_truncate(struct inode * inode)
- * on-disk inode. We do this via i_disksize, which is the value which
- * ext3 *really* writes onto the disk inode.
- */
-- inode->u.ext3_i.i_disksize = inode->i_size;
-+ ei->i_disksize = inode->i_size;
-
- /*
- * From here we block out all ext3_get_block() callers who want to
- * modify the block allocation tree.
- */
-- down_write(&inode->u.ext3_i.truncate_sem);
-+ down_write(&ei->truncate_sem);
-
- if (n == 1) { /* direct blocks */
- ext3_free_data(handle, inode, NULL, i_data+offsets[0],
-@@ -1954,7 +1957,7 @@ do_indirects:
- case EXT3_TIND_BLOCK:
- ;
- }
-- up_write(&inode->u.ext3_i.truncate_sem);
-+ up_write(&ei->truncate_sem);
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- ext3_mark_inode_dirty(handle, inode);
-
-@@ -1983,6 +1986,8 @@ out_stop:
-
- int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
- {
-+ struct super_block *sb = inode->i_sb;
-+ struct ext3_sb_info *sbi = EXT3_SB(sb);
- struct buffer_head *bh = 0;
- unsigned long block;
- unsigned long block_group;
-@@ -1997,23 +2010,19 @@ int ext3_get_inode_loc (struct inode *in
- inode->i_ino != EXT3_JOURNAL_INO &&
-- inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
-- inode->i_ino > le32_to_cpu(
-- inode->i_sb->u.ext3_sb.s_es->s_inodes_count)) {
-- ext3_error (inode->i_sb, "ext3_get_inode_loc",
-- "bad inode number: %lu", inode->i_ino);
-+ inode->i_ino < EXT3_FIRST_INO(sb)) ||
-+ inode->i_ino > le32_to_cpu(sbi->s_es->s_inodes_count)) {
-+ ext3_error (sb, __FUNCTION__, "bad inode #%lu", inode->i_ino);
- goto bad_inode;
- }
-- block_group = (inode->i_ino - 1) / EXT3_INODES_PER_GROUP(inode->i_sb);
-- if (block_group >= inode->i_sb->u.ext3_sb.s_groups_count) {
-- ext3_error (inode->i_sb, "ext3_get_inode_loc",
-- "group >= groups count");
-+ block_group = (inode->i_ino - 1) / sbi->s_inodes_per_group;
-+ if (block_group >= sbi->s_groups_count) {
-+ ext3_error(sb, __FUNCTION__, "group >= groups count");
- goto bad_inode;
- }
-- group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb);
-- desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1);
-- bh = inode->i_sb->u.ext3_sb.s_group_desc[group_desc];
-+ group_desc = block_group >> sbi->s_desc_per_block_bits;
-+ desc = block_group & (sbi->s_desc_per_block - 1);
-+ bh = sbi->s_group_desc[group_desc];
- if (!bh) {
-- ext3_error (inode->i_sb, "ext3_get_inode_loc",
-- "Descriptor not loaded");
-+ ext3_error(sb, __FUNCTION__, "Descriptor not loaded");
- goto bad_inode;
- }
-
-@@ -2021,17 +2022,17 @@ int ext3_get_inode_loc (struct inode *in
- /*
- * Figure out the offset within the block group inode table
- */
-- offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) *
-- EXT3_INODE_SIZE(inode->i_sb);
-+ offset = ((inode->i_ino - 1) % sbi->s_inodes_per_group) *
-+ sbi->s_inode_size;
- block = le32_to_cpu(gdp[desc].bg_inode_table) +
-- (offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
-- if (!(bh = sb_bread(inode->i_sb, block))) {
-- ext3_error (inode->i_sb, "ext3_get_inode_loc",
-+ (offset >> EXT3_BLOCK_SIZE_BITS(sb));
-+ if (!(bh = sb_bread(sb, block))) {
-+ ext3_error (sb, __FUNCTION__,
- "unable to read inode block - "
- "inode=%lu, block=%lu", inode->i_ino, block);
- goto bad_inode;
- }
-- offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
-+ offset &= (EXT3_BLOCK_SIZE(sb) - 1);
-
- iloc->bh = bh;
- iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
-@@ -2047,6 +2048,7 @@ void ext3_read_inode(struct inode * inod
- {
- struct ext3_iloc iloc;
- struct ext3_inode *raw_inode;
-+ struct ext3_inode_info *ei = EXT3_I(inode);
- struct buffer_head *bh;
- int block;
-
-@@ -2054,7 +2056,7 @@ void ext3_read_inode(struct inode * inod
- goto bad_inode;
- bh = iloc.bh;
- raw_inode = iloc.raw_inode;
-- init_rwsem(&inode->u.ext3_i.truncate_sem);
-+ init_rwsem(&ei->truncate_sem);
- inode->i_mode = le16_to_cpu(raw_inode->i_mode);
- inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
- inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
-@@ -2067,7 +2069,7 @@ void ext3_read_inode(struct inode * inod
- inode->i_atime = le32_to_cpu(raw_inode->i_atime);
- inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);
- inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);
-- inode->u.ext3_i.i_dtime = le32_to_cpu(raw_inode->i_dtime);
-+ ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
- /* We now have enough fields to check if the inode was active or not.
- * This is needed because nfsd might try to access dead inodes
- * the test is that same one that e2fsck uses
-@@ -2075,7 +2077,7 @@ void ext3_read_inode(struct inode * inod
- */
- if (inode->i_nlink == 0) {
- if (inode->i_mode == 0 ||
-- !(inode->i_sb->u.ext3_sb.s_mount_state & EXT3_ORPHAN_FS)) {
-+ !(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ORPHAN_FS)) {
- /* this inode is deleted */
- brelse (bh);
- goto bad_inode;
-@@ -2090,33 +2092,33 @@ void ext3_read_inode(struct inode * inod
- * size */
- inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
- inode->i_version = ++event;
-- inode->u.ext3_i.i_flags = le32_to_cpu(raw_inode->i_flags);
-+ ei->i_flags = le32_to_cpu(raw_inode->i_flags);
- #ifdef EXT3_FRAGMENTS
-- inode->u.ext3_i.i_faddr = le32_to_cpu(raw_inode->i_faddr);
-- inode->u.ext3_i.i_frag_no = raw_inode->i_frag;
-- inode->u.ext3_i.i_frag_size = raw_inode->i_fsize;
-+ ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
-+ ei->i_frag_no = raw_inode->i_frag;
-+ ei->i_frag_size = raw_inode->i_fsize;
- #endif
-- inode->u.ext3_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
-+ ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
- if (!S_ISREG(inode->i_mode)) {
-- inode->u.ext3_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
-+ ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
- } else {
- inode->i_size |=
- ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
- }
-- inode->u.ext3_i.i_disksize = inode->i_size;
-+ ei->i_disksize = inode->i_size;
- inode->i_generation = le32_to_cpu(raw_inode->i_generation);
- #ifdef EXT3_PREALLOCATE
-- inode->u.ext3_i.i_prealloc_count = 0;
-+ ei->i_prealloc_count = 0;
- #endif
-- inode->u.ext3_i.i_block_group = iloc.block_group;
-+ ei->i_block_group = iloc.block_group;
-
- /*
- * NOTE! The in-memory inode i_data array is in little-endian order
- * even on big-endian machines: we do NOT byteswap the block numbers!
- */
- for (block = 0; block < EXT3_N_BLOCKS; block++)
-- inode->u.ext3_i.i_data[block] = iloc.raw_inode->i_block[block];
-- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+ ei->i_data[block] = iloc.raw_inode->i_block[block];
-+ INIT_LIST_HEAD(&ei->i_orphan);
-
- brelse (iloc.bh);
-
-@@ -2143,17 +2145,17 @@ void ext3_read_inode(struct inode * inod
- /* inode->i_attr_flags = 0; unused */
-- if (inode->u.ext3_i.i_flags & EXT3_SYNC_FL) {
-+ if (ei->i_flags & EXT3_SYNC_FL) {
- /* inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS; unused */
- inode->i_flags |= S_SYNC;
- }
-- if (inode->u.ext3_i.i_flags & EXT3_APPEND_FL) {
-+ if (ei->i_flags & EXT3_APPEND_FL) {
- /* inode->i_attr_flags |= ATTR_FLAG_APPEND; unused */
- inode->i_flags |= S_APPEND;
- }
-- if (inode->u.ext3_i.i_flags & EXT3_IMMUTABLE_FL) {
-+ if (ei->i_flags & EXT3_IMMUTABLE_FL) {
- /* inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE; unused */
- inode->i_flags |= S_IMMUTABLE;
- }
-- if (inode->u.ext3_i.i_flags & EXT3_NOATIME_FL) {
-+ if (ei->i_flags & EXT3_NOATIME_FL) {
- /* inode->i_attr_flags |= ATTR_FLAG_NOATIME; unused */
- inode->i_flags |= S_NOATIME;
- }
-@@ -2175,6 +2177,7 @@ static int ext3_do_update_inode(handle_t
- struct ext3_iloc *iloc)
- {
- struct ext3_inode *raw_inode = iloc->raw_inode;
-+ struct ext3_inode_info *ei = EXT3_I(inode);
- struct buffer_head *bh = iloc->bh;
- int err = 0, rc, block;
-
-@@ -2192,7 +2195,7 @@ static int ext3_do_update_inode(handle_t
- * Fix up interoperability with old kernels. Otherwise, old inodes get
- * re-used with the upper 16 bits of the uid/gid intact
- */
-- if(!inode->u.ext3_i.i_dtime) {
-+ if(!ei->i_dtime) {
- raw_inode->i_uid_high =
- cpu_to_le16(high_16_bits(inode->i_uid));
- raw_inode->i_gid_high =
-@@ -2210,34 +2213,33 @@ static int ext3_do_update_inode(handle_t
- raw_inode->i_gid_high = 0;
- }
- raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
-- raw_inode->i_size = cpu_to_le32(inode->u.ext3_i.i_disksize);
-+ raw_inode->i_size = cpu_to_le32(ei->i_disksize);
- raw_inode->i_atime = cpu_to_le32(inode->i_atime);
- raw_inode->i_ctime = cpu_to_le32(inode->i_ctime);
- raw_inode->i_mtime = cpu_to_le32(inode->i_mtime);
- raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
-- raw_inode->i_dtime = cpu_to_le32(inode->u.ext3_i.i_dtime);
-- raw_inode->i_flags = cpu_to_le32(inode->u.ext3_i.i_flags);
-+ raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
-+ raw_inode->i_flags = cpu_to_le32(ei->i_flags);
- #ifdef EXT3_FRAGMENTS
-- raw_inode->i_faddr = cpu_to_le32(inode->u.ext3_i.i_faddr);
-- raw_inode->i_frag = inode->u.ext3_i.i_frag_no;
-- raw_inode->i_fsize = inode->u.ext3_i.i_frag_size;
-+ raw_inode->i_faddr = cpu_to_le32(ei->i_faddr);
-+ raw_inode->i_frag = ei->i_frag_no;
-+ raw_inode->i_fsize = ei->i_frag_size;
- #else
- /* If we are not tracking these fields in the in-memory inode,
- * then preserve them on disk, but still initialise them to zero
- * for new inodes. */
-- if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) {
-+ if (ei->i_state & EXT3_STATE_NEW) {
- raw_inode->i_faddr = 0;
- raw_inode->i_frag = 0;
- raw_inode->i_fsize = 0;
- }
- #endif
-- raw_inode->i_file_acl = cpu_to_le32(inode->u.ext3_i.i_file_acl);
-+ raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl);
- if (!S_ISREG(inode->i_mode)) {
-- raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext3_i.i_dir_acl);
-+ raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);
- } else {
-- raw_inode->i_size_high =
-- cpu_to_le32(inode->u.ext3_i.i_disksize >> 32);
-- if (inode->u.ext3_i.i_disksize > 0x7fffffffULL) {
-+ raw_inode->i_size_high = cpu_to_le32(ei->i_disksize >> 32);
-+ if (ei->i_disksize > MAX_NON_LFS) {
- struct super_block *sb = inode->i_sb;
- if (!EXT3_HAS_RO_COMPAT_FEATURE(sb,
- EXT3_FEATURE_RO_COMPAT_LARGE_FILE) ||
-@@ -2247,7 +2249,7 @@ static int ext3_do_update_inode(handle_t
- * created, add a flag to the superblock.
- */
- err = ext3_journal_get_write_access(handle,
-- sb->u.ext3_sb.s_sbh);
-+ EXT3_SB(sb)->s_sbh);
- if (err)
- goto out_brelse;
- ext3_update_dynamic_rev(sb);
-@@ -2256,7 +2258,7 @@ static int ext3_do_update_inode(handle_t
- sb->s_dirt = 1;
- handle->h_sync = 1;
- err = ext3_journal_dirty_metadata(handle,
-- sb->u.ext3_sb.s_sbh);
-+ EXT3_SB(sb)->s_sbh);
- }
- }
- }
-@@ -2265,13 +2267,13 @@ static int ext3_do_update_inode(handle_t
- raw_inode->i_block[0] =
- cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
- else for (block = 0; block < EXT3_N_BLOCKS; block++)
-- raw_inode->i_block[block] = inode->u.ext3_i.i_data[block];
-+ raw_inode->i_block[block] = ei->i_data[block];
-
- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
- rc = ext3_journal_dirty_metadata(handle, bh);
- if (!err)
- err = rc;
-- EXT3_I(inode)->i_state &= ~EXT3_STATE_NEW;
-+ ei->i_state &= ~EXT3_STATE_NEW;
-
- out_brelse:
- brelse (bh);
-@@ -2379,7 +2381,7 @@ int ext3_setattr(struct dentry *dentry,
- }
-
- error = ext3_orphan_add(handle, inode);
-- inode->u.ext3_i.i_disksize = attr->ia_size;
-+ EXT3_I(inode)->i_disksize = attr->ia_size;
- rc = ext3_mark_inode_dirty(handle, inode);
- if (!error)
- error = rc;
-@@ -2622,9 +2624,9 @@ int ext3_change_inode_journal_flag(struc
- */
-
- if (val)
-- inode->u.ext3_i.i_flags |= EXT3_JOURNAL_DATA_FL;
-+ EXT3_I(inode)->i_flags |= EXT3_JOURNAL_DATA_FL;
- else
-- inode->u.ext3_i.i_flags &= ~EXT3_JOURNAL_DATA_FL;
-+ EXT3_I(inode)->i_flags &= ~EXT3_JOURNAL_DATA_FL;
-
- journal_unlock_updates(journal);
-
---- ./fs/ext3/ioctl.c.orig Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/ioctl.c Tue May 7 15:20:52 2002
-@@ -18,13 +18,14 @@
- int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
- unsigned long arg)
- {
-+ struct ext3_inode_info *ei = EXT3_I(inode);
- unsigned int flags;
-
- ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg);
-
- switch (cmd) {
- case EXT3_IOC_GETFLAGS:
-- flags = inode->u.ext3_i.i_flags & EXT3_FL_USER_VISIBLE;
-+ flags = ei->i_flags & EXT3_FL_USER_VISIBLE;
- return put_user(flags, (int *) arg);
- case EXT3_IOC_SETFLAGS: {
- handle_t *handle = NULL;
-@@ -42,7 +42,7 @@ int ext3_ioctl (struct inode * inode, st
- if (get_user(flags, (int *) arg))
- return -EFAULT;
-
-- oldflags = inode->u.ext3_i.i_flags;
-+ oldflags = ei->i_flags;
-
- /* The JOURNAL_DATA flag is modifiable only by root */
- jflag = flags & EXT3_JOURNAL_DATA_FL;
-@@ -79,7 +79,7 @@ int ext3_ioctl (struct inode * inode, st
-
- flags = flags & EXT3_FL_USER_MODIFIABLE;
- flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE;
-- inode->u.ext3_i.i_flags = flags;
-+ ei->i_flags = flags;
-
- if (flags & EXT3_SYNC_FL)
- inode->i_flags |= S_SYNC;
-@@ -155,12 +155,12 @@ flags_err:
- int ret = 0;
-
- set_current_state(TASK_INTERRUPTIBLE);
-- add_wait_queue(&sb->u.ext3_sb.ro_wait_queue, &wait);
-- if (timer_pending(&sb->u.ext3_sb.turn_ro_timer)) {
-+ add_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
-+ if (timer_pending(&EXT3_SB(sb)->turn_ro_timer)) {
- schedule();
- ret = 1;
- }
-- remove_wait_queue(&sb->u.ext3_sb.ro_wait_queue, &wait);
-+ remove_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
- return ret;
- }
- #endif
---- ./fs/ext3/namei.c.orig Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/namei.c Tue May 7 16:05:51 2002
-@@ -636,7 +636,7 @@ static struct buffer_head * ext3_find_en
- }
-
- nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
-- start = dir->u.ext3_i.i_dir_start_lookup;
-+ start = EXT3_I(dir)->i_dir_start_lookup;
- if (start >= nblocks)
- start = 0;
- block = start;
-@@ -677,7 +677,7 @@ restart:
- i = search_dirblock(bh, dir, dentry,
- block << EXT3_BLOCK_SIZE_BITS(sb), res_dir);
- if (i == 1) {
-- dir->u.ext3_i.i_dir_start_lookup = block;
-+ EXT3_I(dir)->i_dir_start_lookup = block;
- ret = bh;
- goto cleanup_and_exit;
- } else {
-@@ -1419,7 +1419,7 @@ int ext3_orphan_add(handle_t *handle, st
- int err = 0, rc;
-
- lock_super(sb);
-- if (!list_empty(&inode->u.ext3_i.i_orphan))
-+ if (!list_empty(&EXT3_I(inode)->i_orphan))
- goto out_unlock;
-
- /* Orphan handling is only valid for files with data blocks
-@@ -1430,8 +1430,8 @@ int ext3_orphan_add(handle_t *handle, st
- J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
-
-- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");
-- err = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);
-+ BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "get_write_access");
-+ err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
- if (err)
- goto out_unlock;
-
-@@ -1442,7 +1442,7 @@ int ext3_orphan_add(handle_t *handle, st
- /* Insert this inode at the head of the on-disk orphan list... */
- NEXT_ORPHAN(inode) = le32_to_cpu(EXT3_SB(sb)->s_es->s_last_orphan);
- EXT3_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
-- err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);
-+ err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
- rc = ext3_mark_iloc_dirty(handle, inode, &iloc);
- if (!err)
- err = rc;
-@@ -1456,7 +1456,7 @@ int ext3_orphan_add(handle_t *handle, st
- * This is safe: on error we're going to ignore the orphan list
- * anyway on the next recovery. */
- if (!err)
-- list_add(&inode->u.ext3_i.i_orphan, &EXT3_SB(sb)->s_orphan);
-+ list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);
-
- jbd_debug(4, "superblock will point to %ld\n", inode->i_ino);
- jbd_debug(4, "orphan inode %ld will point to %d\n",
-@@ -714,25 +770,25 @@
- int ext3_orphan_del(handle_t *handle, struct inode *inode)
- {
- struct list_head *prev;
-+ struct ext3_inode_info *ei = EXT3_I(inode);
- struct ext3_sb_info *sbi;
- ino_t ino_next;
- struct ext3_iloc iloc;
- int err = 0;
-
- lock_super(inode->i_sb);
-- if (list_empty(&inode->u.ext3_i.i_orphan)) {
-+ if (list_empty(&ei->i_orphan)) {
- unlock_super(inode->i_sb);
- return 0;
- }
-
- ino_next = NEXT_ORPHAN(inode);
-- prev = inode->u.ext3_i.i_orphan.prev;
-+ prev = ei->i_orphan.prev;
- sbi = EXT3_SB(inode->i_sb);
-
- jbd_debug(4, "remove inode %ld from orphan list\n", inode->i_ino);
-
-- list_del(&inode->u.ext3_i.i_orphan);
-- INIT_LIST_HEAD(&inode->u.ext3_i.i_orphan);
-+ list_del_init(&ei->i_orphan);
-
- /* If we're on an error path, we may not have a valid
- * transaction handle with which to update the orphan list on
-@@ -1520,9 +1520,8 @@ int ext3_orphan_del(handle_t *handle, st
- err = ext3_journal_dirty_metadata(handle, sbi->s_sbh);
- } else {
- struct ext3_iloc iloc2;
-- struct inode *i_prev =
-- list_entry(prev, struct inode, u.ext3_i.i_orphan);
--
-+ struct inode *i_prev = orphan_list_entry(prev);
-+
- jbd_debug(4, "orphan inode %ld will point to %ld\n",
- i_prev->i_ino, ino_next);
- err = ext3_reserve_inode_write(handle, i_prev, &iloc2);
-@@ -1695,10 +1695,10 @@ static int ext3_symlink (struct inode *
- goto out_no_entry;
- } else {
- inode->i_op = &ext3_fast_symlink_inode_operations;
-- memcpy((char*)&inode->u.ext3_i.i_data,symname,l);
-+ memcpy((char*)&EXT3_I(inode)->i_data,symname,l);
- inode->i_size = l-1;
- }
-- inode->u.ext3_i.i_disksize = inode->i_size;
-+ EXT3_I(inode)->i_disksize = inode->i_size;
- err = ext3_add_nondir(handle, dentry, inode);
- ext3_mark_inode_dirty(handle, inode);
- out_stop:
---- ./fs/ext3/super.c.orig Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/super.c Tue May 7 16:05:44 2002
-@@ -121,7 +121,7 @@ static int ext3_error_behaviour(struct s
- /* If no overrides were specified on the mount, then fall back
- * to the default behaviour set in the filesystem's superblock
- * on disk. */
-- switch (le16_to_cpu(sb->u.ext3_sb.s_es->s_errors)) {
-+ switch (le16_to_cpu(EXT3_SB(sb)->s_es->s_errors)) {
- case EXT3_ERRORS_PANIC:
- return EXT3_ERRORS_PANIC;
- case EXT3_ERRORS_RO:
-@@ -269,9 +269,9 @@ void ext3_abort (struct super_block * sb
- return;
-
- printk (KERN_CRIT "Remounting filesystem read-only\n");
-- sb->u.ext3_sb.s_mount_state |= EXT3_ERROR_FS;
-+ EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
- sb->s_flags |= MS_RDONLY;
-- sb->u.ext3_sb.s_mount_opt |= EXT3_MOUNT_ABORT;
-+ EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
- journal_abort(EXT3_SB(sb)->s_journal, -EIO);
- }
-
-@@ -377,8 +377,6 @@ static int ext3_blkdev_remove(struct ext3
- return ret;
- }
-
--#define orphan_list_entry(l) list_entry((l), struct inode, u.ext3_i.i_orphan)
--
- static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
- {
- struct list_head *l;
-@@ -818,7 +818,7 @@ static void ext3_orphan_cleanup (struct
- sb->s_flags &= ~MS_RDONLY;
- }
-
-- if (sb->u.ext3_sb.s_mount_state & EXT3_ERROR_FS) {
-+ if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) {
- if (es->s_last_orphan)
- jbd_debug(1, "Errors on filesystem, "
- "clearing orphan list.\n");
-@@ -1463,12 +1463,14 @@ static void ext3_commit_super (struct su
- struct ext3_super_block * es,
- int sync)
- {
-+ struct buffer_head *sbh = EXT3_SB(sb)->s_sbh;
-+
- es->s_wtime = cpu_to_le32(CURRENT_TIME);
-- BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "marking dirty");
-- mark_buffer_dirty(sb->u.ext3_sb.s_sbh);
-+ BUFFER_TRACE(sbh, "marking dirty");
-+ mark_buffer_dirty(sbh);
- if (sync) {
-- ll_rw_block(WRITE, 1, &sb->u.ext3_sb.s_sbh);
-- wait_on_buffer(sb->u.ext3_sb.s_sbh);
-+ ll_rw_block(WRITE, 1, &sbh);
-+ wait_on_buffer(sbh);
- }
- }
-
-@@ -1519,7 +1521,7 @@ static void ext3_clear_journal_err(struc
- ext3_warning(sb, __FUNCTION__, "Marking fs in need of "
- "filesystem check.");
-
-- sb->u.ext3_sb.s_mount_state |= EXT3_ERROR_FS;
-+ EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
- es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
- ext3_commit_super (sb, es, 1);
-
---- ./fs/ext3/symlink.c.orig Fri Apr 12 10:27:49 2002
-+++ ./fs/ext3/symlink.c Tue May 7 15:25:39 2002
-@@ -23,13 +23,13 @@
-
- static int ext3_readlink(struct dentry *dentry, char *buffer, int buflen)
- {
-- char *s = (char *)dentry->d_inode->u.ext3_i.i_data;
-- return vfs_readlink(dentry, buffer, buflen, s);
-+ struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
-+ return vfs_readlink(dentry, buffer, buflen, (char *)ei->i_data);
- }
-
- static int ext3_follow_link(struct dentry *dentry, struct nameidata *nd)
- {
-- char *s = (char *)dentry->d_inode->u.ext3_i.i_data;
-- return vfs_follow_link(nd, s);
-+ struct ext3_inode_info *ei = EXT3_I(dentry->d_inode);
-+ return vfs_follow_link(nd, (char*)ei->i_data);
- }
-
---- ./include/linux/ext3_fs.h.orig Tue Apr 16 14:27:25 2002
-+++ ./include/linux/ext3_fs.h Tue May 7 16:47:36 2002
-@@ -84,22 +84,25 @@
- #define EXT3_MIN_BLOCK_SIZE 1024
- #define EXT3_MAX_BLOCK_SIZE 4096
- #define EXT3_MIN_BLOCK_LOG_SIZE 10
-+
- #ifdef __KERNEL__
--# define EXT3_BLOCK_SIZE(s) ((s)->s_blocksize)
--#else
--# define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
--#endif
--#define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
--#ifdef __KERNEL__
--# define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
--#else
--# define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
--#endif
--#ifdef __KERNEL__
--#define EXT3_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext3_sb.s_addr_per_block_bits)
--#define EXT3_INODE_SIZE(s) ((s)->u.ext3_sb.s_inode_size)
--#define EXT3_FIRST_INO(s) ((s)->u.ext3_sb.s_first_ino)
-+#define EXT3_SB(sb) (&((sb)->u.ext3_sb))
-+#define EXT3_I(inode) (&((inode)->u.ext3_i))
-+
-+#define EXT3_BLOCK_SIZE(s) ((s)->s_blocksize)
-+#define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-+#define EXT3_ADDR_PER_BLOCK_BITS(s) (EXT3_SB(s)->s_addr_per_block_bits)
-+#define EXT3_INODE_SIZE(s) (EXT3_SB(s)->s_inode_size)
-+#define EXT3_FIRST_INO(s) (EXT3_SB(s)->s_first_ino)
- #else
-+
-+/* Assume that user mode programs are passing in an ext3fs superblock, not
-+ * a kernel struct super_block. This will allow us to call the feature-test
-+ * macros from user land. */
-+#define EXT3_SB(sb) (sb)
-+
-+#define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
-+#define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
- #define EXT3_INODE_SIZE(s) (((s)->s_rev_level == EXT3_GOOD_OLD_REV) ? \
- EXT3_GOOD_OLD_INODE_SIZE : \
- (s)->s_inode_size)
-@@ -108,6 +110,7 @@
- EXT3_GOOD_OLD_FIRST_INO : \
- (s)->s_first_ino)
- #endif
-+#define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
-
- /*
- * Macro-instructions used to manage fragments
-@@ -116,8 +120,8 @@
- #define EXT3_MAX_FRAG_SIZE 4096
- #define EXT3_MIN_FRAG_LOG_SIZE 10
- #ifdef __KERNEL__
--# define EXT3_FRAG_SIZE(s) ((s)->u.ext3_sb.s_frag_size)
--# define EXT3_FRAGS_PER_BLOCK(s) ((s)->u.ext3_sb.s_frags_per_block)
-+# define EXT3_FRAG_SIZE(s) (EXT3_SB(s)->s_frag_size)
-+# define EXT3_FRAGS_PER_BLOCK(s) (EXT3_SB(s)->s_frags_per_block)
- #else
- # define EXT3_FRAG_SIZE(s) (EXT3_MIN_FRAG_SIZE << (s)->s_log_frag_size)
- # define EXT3_FRAGS_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / EXT3_FRAG_SIZE(s))
-@@ -163,15 +167,13 @@
- /*
- * Macro-instructions used to manage group descriptors
- */
-+# define EXT3_BLOCKS_PER_GROUP(s) (EXT3_SB(s)->s_blocks_per_group)
-+# define EXT3_INODES_PER_GROUP(s) (EXT3_SB(s)->s_inodes_per_group)
- #ifdef __KERNEL__
--# define EXT3_BLOCKS_PER_GROUP(s) ((s)->u.ext3_sb.s_blocks_per_group)
--# define EXT3_DESC_PER_BLOCK(s) ((s)->u.ext3_sb.s_desc_per_block)
--# define EXT3_INODES_PER_GROUP(s) ((s)->u.ext3_sb.s_inodes_per_group)
--# define EXT3_DESC_PER_BLOCK_BITS(s) ((s)->u.ext3_sb.s_desc_per_block_bits)
-+# define EXT3_DESC_PER_BLOCK(s) (EXT3_SB(s)->s_desc_per_block)
-+# define EXT3_DESC_PER_BLOCK_BITS(s) (EXT3_SB(s)->s_desc_per_block_bits)
- #else
--# define EXT3_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group)
- # define EXT3_DESC_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_group_desc))
--# define EXT3_INODES_PER_GROUP(s) ((s)->s_inodes_per_group)
- #endif
-
- /*
-@@ -344,7 +347,7 @@
- #ifndef _LINUX_EXT2_FS_H
- #define clear_opt(o, opt) o &= ~EXT3_MOUNT_##opt
- #define set_opt(o, opt) o |= EXT3_MOUNT_##opt
--#define test_opt(sb, opt) ((sb)->u.ext3_sb.s_mount_opt & \
-+#define test_opt(sb, opt) (EXT3_SB(sb)->s_mount_opt & \
- EXT3_MOUNT_##opt)
- #else
- #define EXT2_MOUNT_NOLOAD EXT3_MOUNT_NOLOAD
-@@ -441,17 +443,11 @@
- /*EC*/ __u32 s_reserved[197]; /* Padding to the end of the block */
- };
-
--#ifdef __KERNEL__
--#define EXT3_SB(sb) (&((sb)->u.ext3_sb))
--#define EXT3_I(inode) (&((inode)->u.ext3_i))
--#else
--/* Assume that user mode programs are passing in an ext3fs superblock, not
-- * a kernel struct super_block. This will allow us to call the feature-test
-- * macros from user land. */
--#define EXT3_SB(sb) (sb)
--#endif
--
--#define NEXT_ORPHAN(inode) (inode)->u.ext3_i.i_dtime
-+#define NEXT_ORPHAN(inode) EXT3_I(inode)->i_dtime
-+static inline struct inode *orphan_list_entry(struct list_head *l)
-+{
-+ return list_entry(l, struct inode, u.ext3_i.i_orphan);
-+}
-
- /*
- * Codes for operating systems
---- ./include/linux/ext3_jbd.h.orig Tue May 7 14:44:08 2002
-+++ ./include/linux/ext3_jbd.h Tue May 7 14:44:43 2002
-@@ -291,7 +291,7 @@
- return 1;
- if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
- return 1;
-- if (inode->u.ext3_i.i_flags & EXT3_JOURNAL_DATA_FL)
-+ if (EXT3_I(inode)->i_flags & EXT3_JOURNAL_DATA_FL)
- return 1;
- return 0;
- }
+++ /dev/null
---- linux-2.4.17/fs/extN/super.c.orig Fri Dec 21 10:41:55 2001
-+++ linux-2.4.17/fs/extN/super.c Fri Mar 22 11:00:41 2002
-@@ -1742,7 +1742,7 @@
- unregister_filesystem(&extN_fs_type);
- }
-
--EXPORT_NO_SYMBOLS;
-+EXPORT_SYMBOL(extN_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
- MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
+++ /dev/null
---- ./include/linux/extN_fs.h.orig Tue May 7 17:06:03 2002
-+++ ./include/linux/extN_fs.h Tue May 7 17:07:11 2002
-@@ -17,6 +17,8 @@
- #define _LINUX_EXTN_FS_H
-
- #include <linux/types.h>
-+#include <linux/extN_fs_sb.h>
-+#include <linux/extN_fs_i.h>
-
- /*
- * The second extended filesystem constants/structures
-@@ -86,8 +88,8 @@
- #define EXTN_MIN_BLOCK_LOG_SIZE 10
-
- #ifdef __KERNEL__
--#define EXTN_SB(sb) (&((sb)->u.extN_sb))
--#define EXTN_I(inode) (&((inode)->u.extN_i))
-+#define EXTN_SB(sb) ((struct extN_sb_info *)&((sb)->u.generic_sbp))
-+#define EXTN_I(inode) ((struct extN_inode_info *)&((inode)->u.generic_ip))
-
- #define EXTN_BLOCK_SIZE(s) ((s)->s_blocksize)
- #define EXTN_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -447,7 +447,9 @@
- #define NEXT_ORPHAN(inode) EXTN_I(inode)->i_dtime
- static inline struct inode *orphan_list_entry(struct list_head *l)
- {
-- return list_entry(l, struct inode, u.extN_i.i_orphan);
-+ return ((struct inode *)((char *)l -
-+ (unsigned long)(offsetof(struct inode, u.generic_ip) +
-+ offsetof(struct extN_inode_info, i_orphan))));
- }
-
- /*
+++ /dev/null
---- linux-2.4.17/fs/extN/super.c.orig Fri Dec 21 10:41:55 2001
-+++ linux-2.4.17/fs/extN/super.c Fri Mar 22 11:00:41 2002
-@@ -1344,10 +1342,10 @@
- printk(KERN_ERR "EXTN-fs: I/O error on journal device\n");
- goto out_journal;
- }
-- if (ntohl(journal->j_superblock->s_nr_users) != 1) {
-+ if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {
- printk(KERN_ERR "EXTN-fs: External journal has more than one "
- "user (unsupported) - %d\n",
-- ntohl(journal->j_superblock->s_nr_users));
-+ be32_to_cpu(journal->j_superblock->s_nr_users));
- goto out_journal;
- }
- EXTN_SB(sb)->journal_bdev = bdev;
+++ /dev/null
---- ./fs/ext3/super.c 2002/03/05 06:18:59 2.1
-+++ ./fs/ext3/super.c 2002/03/05 06:26:56
-@@ -529,6 +529,12 @@
- "EXT3 Check option not supported\n");
- #endif
- }
-+ else if (!strcmp (this_char, "index"))
-+#ifdef CONFIG_EXT3_INDEX
-+ set_opt (*mount_options, INDEX);
-+#else
-+ printk("EXT3 index option not supported\n");
-+#endif
- else if (!strcmp (this_char, "debug"))
- set_opt (*mount_options, DEBUG);
- else if (!strcmp (this_char, "errors")) {
-@@ -702,6 +708,12 @@ static int ext3_setup_super(struct super
- es->s_mtime = cpu_to_le32(CURRENT_TIME);
- ext3_update_dynamic_rev(sb);
- EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-+
-+ if (test_opt(sb, INDEX))
-+ EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX);
-+ else if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
-+ set_opt (EXT3_SB(sb)->s_mount_opt, INDEX);
-+
- ext3_commit_super (sb, es, 1);
- if (test_opt (sb, DEBUG))
- printk (KERN_INFO
---- ./fs/ext3/namei.c 2002/03/05 06:18:59 2.1
-+++ ./fs/ext3/namei.c 2002/03/06 00:13:18
-@@ -16,6 +16,10 @@
- * David S. Miller (davem@caip.rutgers.edu), 1995
- * Directory entry file type support and forward compatibility hooks
- * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
-+ * Hash Tree Directory indexing (c)
-+ * Daniel Phillips, 2001
-+ * Hash Tree Directory indexing porting
-+ * Christopher Li, 2002
- */
-
- #include <linux/fs.h>
-@@ -33,7 +33,7 @@
- #include <linux/string.h>
- #include <linux/locks.h>
- #include <linux/quotaops.h>
--
-+#include <linux/slab.h>
-
- /*
- * define how far ahead to read directories while searching them.
-@@ -38,6 +42,433 @@
- #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
- #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
-
-+static struct buffer_head *ext3_append(handle_t *handle,
-+ struct inode *inode,
-+ u32 *block, int *err)
-+{
-+ struct buffer_head *bh;
-+
-+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
-+
-+ if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
-+ inode->i_size += inode->i_sb->s_blocksize;
-+ EXT3_I(inode)->i_disksize = inode->i_size;
-+ ext3_journal_get_write_access(handle,bh);
-+ }
-+ return bh;
-+}
-+
-+#ifndef assert
-+#define assert(test) J_ASSERT(test)
-+#endif
-+
-+#ifndef swap
-+#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0)
-+#endif
-+
-+typedef struct { u32 v; } le_u32;
-+typedef struct { u16 v; } le_u16;
-+
-+#define dxtrace_on(command) command
-+#define dxtrace_off(command)
-+#define dxtrace dxtrace_off
-+
-+struct fake_dirent
-+{
-+ /*le*/u32 inode;
-+ /*le*/u16 rec_len;
-+ u8 name_len;
-+ u8 file_type;
-+};
-+
-+struct dx_countlimit
-+{
-+ le_u16 limit;
-+ le_u16 count;
-+};
-+
-+struct dx_entry
-+{
-+ le_u32 hash;
-+ le_u32 block;
-+};
-+
-+/*
-+ * dx_root_info is laid out so that if it should somehow get overlaid by a
-+ * dirent the two low bits of the hash version will be zero. Therefore, the
-+ * hash version mod 4 should never be 0. Sincerely, the paranoia department.
-+ */
-+
-+struct dx_root
-+{
-+ struct fake_dirent dot;
-+ char dot_name[4];
-+ struct fake_dirent dotdot;
-+ char dotdot_name[4];
-+ struct dx_root_info
-+ {
-+ le_u32 reserved_zero;
-+ u8 hash_version; /* 0 now, 1 at release */
-+ u8 info_length; /* 8 */
-+ u8 indirect_levels;
-+ u8 unused_flags;
-+ }
-+ info;
-+ struct dx_entry entries[0];
-+};
-+
-+struct dx_node
-+{
-+ struct fake_dirent fake;
-+ struct dx_entry entries[0];
-+};
-+
-+
-+struct dx_frame
-+{
-+ struct buffer_head *bh;
-+ struct dx_entry *entries;
-+ struct dx_entry *at;
-+};
-+
-+struct dx_map_entry
-+{
-+ u32 hash;
-+ u32 offs;
-+};
-+
-+typedef struct ext3_dir_entry_2 ext3_dirent;
-+static inline unsigned dx_get_block (struct dx_entry *entry);
-+static void dx_set_block (struct dx_entry *entry, unsigned value);
-+static inline unsigned dx_get_hash (struct dx_entry *entry);
-+static void dx_set_hash (struct dx_entry *entry, unsigned value);
-+static unsigned dx_get_count (struct dx_entry *entries);
-+static unsigned dx_get_limit (struct dx_entry *entries);
-+static void dx_set_count (struct dx_entry *entries, unsigned value);
-+static void dx_set_limit (struct dx_entry *entries, unsigned value);
-+static unsigned dx_root_limit (struct inode *dir, unsigned infosize);
-+static unsigned dx_node_limit (struct inode *dir);
-+static unsigned dx_hack_hash (const u8 *name, int len);
-+static struct dx_frame *dx_probe (struct inode *dir, u32 hash, struct dx_frame *frame);
-+static void dx_release (struct dx_frame *frames);
-+static int dx_make_map (ext3_dirent *de, int size, struct dx_map_entry map[]);
-+static void dx_sort_map(struct dx_map_entry *map, unsigned count);
-+static ext3_dirent *dx_copy_dirents (char *from, char *to,
-+ struct dx_map_entry *map, int count);
-+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
-+
-+
-+#ifdef CONFIG_EXT3_INDEX
-+/*
-+ * Future: use high four bits of block for coalesce-on-delete flags
-+ * Mask them off for now.
-+ */
-+
-+static inline unsigned dx_get_block (struct dx_entry *entry)
-+{
-+ return le32_to_cpu(entry->block.v) & 0x00ffffff;
-+}
-+
-+static inline void dx_set_block (struct dx_entry *entry, unsigned value)
-+{
-+ entry->block.v = cpu_to_le32(value);
-+}
-+
-+static inline unsigned dx_get_hash (struct dx_entry *entry)
-+{
-+ return le32_to_cpu(entry->hash.v);
-+}
-+
-+static inline void dx_set_hash (struct dx_entry *entry, unsigned value)
-+{
-+ entry->hash.v = cpu_to_le32(value);
-+}
-+
-+static inline unsigned dx_get_count (struct dx_entry *entries)
-+{
-+ return le16_to_cpu(((struct dx_countlimit *) entries)->count.v);
-+}
-+
-+static inline unsigned dx_get_limit (struct dx_entry *entries)
-+{
-+ return le16_to_cpu(((struct dx_countlimit *) entries)->limit.v);
-+}
-+
-+static inline void dx_set_count (struct dx_entry *entries, unsigned value)
-+{
-+ ((struct dx_countlimit *) entries)->count.v = cpu_to_le16(value);
-+}
-+
-+static inline void dx_set_limit (struct dx_entry *entries, unsigned value)
-+{
-+ ((struct dx_countlimit *) entries)->limit.v = cpu_to_le16(value);
-+}
-+
-+static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
-+{
-+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) -
-+ EXT3_DIR_REC_LEN(2) - infosize;
-+ return 0? 20: entry_space / sizeof(struct dx_entry);
-+}
-+
-+static inline unsigned dx_node_limit (struct inode *dir)
-+{
-+ unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0);
-+ return 0? 22: entry_space / sizeof(struct dx_entry);
-+}
-+
-+/* Hash function - not bad, but still looking for an ideal default */
-+
-+static unsigned dx_hack_hash (const u8 *name, int len)
-+{
-+ u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
-+ while (len--)
-+ {
-+ u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
-+ if (hash & 0x80000000) hash -= 0x7fffffff;
-+ hash1 = hash0;
-+ hash0 = hash;
-+ }
-+ return hash0;
-+}
-+
-+#define dx_hash(s,n) (dx_hack_hash(s,n) << 1)
-+
-+/*
-+ * Debug
-+ */
-+static void dx_show_index (char * label, struct dx_entry *entries)
-+{
-+ int i, n = dx_get_count (entries);
-+ printk("%s index ", label);
-+ for (i = 0; i < n; i++)
-+ {
-+ printk("%x->%u ", i? dx_get_hash(entries + i): 0, dx_get_block(entries + i));
-+ }
-+ printk("\n");
-+}
-+
-+struct stats
-+{
-+ unsigned names;
-+ unsigned space;
-+ unsigned bcount;
-+};
-+
-+static struct stats dx_show_leaf (ext3_dirent *de, int size, int show_names)
-+{
-+ unsigned names = 0, space = 0;
-+ char *base = (char *) de;
-+ printk("names: ");
-+ while ((char *) de < base + size)
-+ {
-+ if (de->inode)
-+ {
-+ if (show_names)
-+ {
-+ int len = de->name_len;
-+ char *name = de->name;
-+ while (len--) printk("%c", *name++);
-+ printk(":%x.%u ", dx_hash (de->name, de->name_len), ((char *) de - base));
-+ }
-+ space += EXT3_DIR_REC_LEN(de->name_len);
-+ names++;
-+ }
-+ de = (ext3_dirent *) ((char *) de + le16_to_cpu(de->rec_len));
-+ }
-+ printk("(%i)\n", names);
-+ return (struct stats) { names, space, 1 };
-+}
-+
-+struct stats dx_show_entries (struct inode *dir, struct dx_entry *entries, int levels)
-+{
-+ unsigned blocksize = dir->i_sb->s_blocksize;
-+ unsigned count = dx_get_count (entries), names = 0, space = 0, i;
-+ unsigned bcount = 0;
-+ struct buffer_head *bh;
-+ int err;
-+ printk("%i indexed blocks...\n", count);
-+ for (i = 0; i < count; i++, entries++)
-+ {
-+ u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0;
-+ u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash;
-+ struct stats stats;
-+ printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range);
-+ if (!(bh = ext3_bread (NULL,dir, block, 0,&err))) continue;
-+ stats = levels?
-+ dx_show_entries (dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
-+ dx_show_leaf ((ext3_dirent *) bh->b_data, blocksize, 0);
-+ names += stats.names;
-+ space += stats.space;
-+ bcount += stats.bcount;
-+ brelse (bh);
-+ }
-+ if (bcount)
-+ printk("%snames %u, fullness %u (%u%%)\n", levels?"":" ",
-+ names, space/bcount,(space/bcount)*100/blocksize);
-+ return (struct stats) { names, space, bcount};
-+}
-+
-+/*
-+ * Probe for a directory leaf block to search
-+ */
-+
-+static struct dx_frame *
-+dx_probe(struct inode *dir, u32 hash, struct dx_frame *frame_in)
-+{
-+ unsigned count, indirect;
-+ struct dx_entry *at, *entries, *p, *q, *m;
-+ struct dx_root *root;
-+ struct buffer_head *bh;
-+ struct dx_frame *frame = frame_in;
-+ int err;
-+
-+ frame->bh = NULL;
-+ if (!(bh = ext3_bread(NULL, dir, 0, 0, &err)))
-+ goto fail;
-+ root = (struct dx_root *) bh->b_data;
-+ if (root->info.hash_version > 0 || root->info.unused_flags & 1) {
-+ brelse(bh);
-+ goto fail;
-+ }
-+ if ((indirect = root->info.indirect_levels) > 1) {
-+ brelse(bh);
-+ goto fail;
-+ }
-+ entries = (struct dx_entry *) (((char *) &root->info) + root->info.info_length);
-+ assert (dx_get_limit(entries) == dx_root_limit(dir, root->info.info_length));
-+ dxtrace (printk("Look up %x", hash));
-+ while (1)
-+ {
-+ count = dx_get_count(entries);
-+ assert (count && count <= dx_get_limit(entries));
-+ p = entries + 1;
-+ q = entries + count - 1;
-+ while (p <= q)
-+ {
-+ m = p + (q - p)/2;
-+ dxtrace(printk("."));
-+ if (dx_get_hash(m) > hash)
-+ q = m - 1;
-+ else
-+ p = m + 1;
-+ }
-+
-+ if (0) // linear search cross check
-+ {
-+ unsigned n = count - 1;
-+ at = entries;
-+ while (n--)
-+ {
-+ dxtrace(printk(","));
-+ if (dx_get_hash(++at) > hash)
-+ {
-+ at--;
-+ break;
-+ }
-+ }
-+ assert (at == p - 1);
-+ }
-+
-+ at = p - 1;
-+ dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
-+ frame->bh = bh;
-+ frame->entries = entries;
-+ frame->at = at;
-+ if (!indirect--) return frame;
-+ if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0,&err)))
-+ goto fail2;
-+ at = entries = ((struct dx_node *) bh->b_data)->entries;
-+ assert (dx_get_limit(entries) == dx_node_limit (dir));
-+ frame++;
-+ }
-+fail2:
-+ while (frame >= frame_in) {
-+ brelse(frame->bh);
-+ frame--;
-+ }
-+fail:
-+ return NULL;
-+}
-+
-+static void dx_release (struct dx_frame *frames)
-+{
-+ if (frames[0].bh == NULL)
-+ return;
-+
-+ if (((struct dx_root *)frames[0].bh->b_data)->info.indirect_levels)
-+ brelse (frames[1].bh);
-+ brelse (frames[0].bh);
-+}
-+
-+/*
-+ * Directory block splitting, compacting
-+ */
-+
-+static int dx_make_map (ext3_dirent *de, int size, struct dx_map_entry map[])
-+{
-+ int count = 0;
-+ char *base = (char *) de;
-+ while ((char *) de < base + size) {
-+ if (de->name_len && de->inode) {
-+ map[count].hash = dx_hash (de->name, de->name_len);
-+ map[count].offs = (u32) ((char *) de - base);
-+ count++;
-+ }
-+ de = (ext3_dirent *) ((char *) de + le16_to_cpu(de->rec_len));
-+ }
-+ return count;
-+}
-+
-+static void dx_sort_map (struct dx_map_entry *map, unsigned count)
-+{
-+ struct dx_map_entry *p, *q, *top = map + count - 1;
-+ int more;
-+ /* Combsort until bubble sort doesn't suck */
-+ while (count > 2)
-+ {
-+ count = count*10/13;
-+ if (count - 9 < 2) /* 9, 10 -> 11 */
-+ count = 11;
-+ for (p = top, q = p - count; q >= map; p--, q--)
-+ if (p->hash < q->hash)
-+ swap(*p, *q);
-+ }
-+ /* Garden variety bubble sort */
-+ do {
-+ more = 0;
-+ q = top;
-+ while (q-- > map)
-+ {
-+ if (q[1].hash >= q[0].hash)
-+ continue;
-+ swap(*(q+1), *q);
-+ more = 1;
-+ }
-+ } while(more);
-+}
-+
-+static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
-+{
-+ struct dx_entry *entries = frame->entries;
-+ struct dx_entry *old = frame->at, *new = old + 1;
-+ int count = dx_get_count(entries);
-+
-+ assert(count < dx_get_limit(entries));
-+ assert(old < entries + count);
-+ memmove(new + 1, new, (char *)(entries + count) - (char *)(new));
-+ dx_set_hash(new, hash);
-+ dx_set_block(new, block);
-+ dx_set_count(entries, count + 1);
-+}
-+#endif
-+
-+static void ext3_update_dx_flag(struct inode *inode)
-+{
-+ if (!test_opt(inode->i_sb, INDEX))
-+ EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL;
-+}
-+
- /*
- * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure.
- *
-@@ -95,6 +529,15 @@
- }
-
- /*
-+ * p is at least 6 bytes before the end of page
-+ */
-+static inline ext3_dirent *ext3_next_entry(ext3_dirent *p)
-+{
-+ return (ext3_dirent *)((char*)p + le16_to_cpu(p->rec_len));
-+}
-+
-+
-+/*
- * ext3_find_entry()
- *
- * finds an entry in the specified directory with the wanted name. It
-@@ -105,6 +548,8 @@
- * The returned buffer_head has ->b_count elevated. The caller is expected
- * to brelse() it when appropriate.
- */
-+
-+
- static struct buffer_head * ext3_find_entry (struct dentry *dentry,
- struct ext3_dir_entry_2 ** res_dir)
- {
-@@ -119,10 +564,76 @@
- int num = 0;
- int nblocks, i, err;
- struct inode *dir = dentry->d_parent->d_inode;
-+ int namelen;
-+ const u8 *name;
-+ unsigned blocksize;
-+ ext3_dirent *de, *top;
-
- *res_dir = NULL;
- sb = dir->i_sb;
-+ blocksize = sb->s_blocksize;
-+ namelen = dentry->d_name.len;
-+ name = dentry->d_name.name;
-+ if (namelen > EXT3_NAME_LEN)
-+ return NULL;
-+ if (ext3_dx && is_dx(dir)) {
-+ u32 hash = dx_hash (name, namelen);
-+ struct dx_frame frames[2], *frame;
-+ if (!(frame = dx_probe (dir, hash, frames)))
-+ return NULL;
-+dxnext:
-+ block = dx_get_block(frame->at);
-+ if (!(bh = ext3_bread (NULL,dir, block, 0, &err)))
-+ goto dxfail;
-+ de = (ext3_dirent *) bh->b_data;
-+ top = (ext3_dirent *) ((char *) de + blocksize -
-+ EXT3_DIR_REC_LEN(0));
-+ for (; de < top; de = ext3_next_entry(de))
-+ if (ext3_match (namelen, name, de)) {
-+ if (!ext3_check_dir_entry("ext3_find_entry",
-+ dir, de, bh,
-+ (block<<EXT3_BLOCK_SIZE_BITS(sb))
-+ +((char *)de - bh->b_data))) {
-+ brelse (bh);
-+ goto dxfail;
-+ }
-+ *res_dir = de;
-+ goto dxfound;
-+ }
-+ brelse (bh);
-+ /* Same hash continues in next block? Search on. */
-+ if (++(frame->at) == frame->entries + dx_get_count(frame->entries))
-+ {
-+ struct buffer_head *bh2;
-+ if (frame == frames)
-+ goto dxfail;
-+ if (++(frames->at) == frames->entries + dx_get_count(frames->entries))
-+ goto dxfail;
-+ /* should omit read if not continued */
-+ if (!(bh2 = ext3_bread (NULL, dir,
-+ dx_get_block(frames->at),
-+ 0, &err)))
-+ goto dxfail;
-+ brelse (frame->bh);
-+ frame->bh = bh2;
-+ frame->at = frame->entries = ((struct dx_node *) bh2->b_data)->entries;
-+ /* Subtle: the 0th entry has the count, find the hash in frame above */
-+ if ((dx_get_hash(frames->at) & -2) == hash)
-+ goto dxnext;
-+ goto dxfail;
-+ }
-+ if ((dx_get_hash(frame->at) & -2) == hash)
-+ goto dxnext;
-+dxfail:
-+ dxtrace(printk("%s not found\n", name));
-+ dx_release (frames);
-+ return NULL;
-+dxfound:
-+ dx_release (frames);
-+ return bh;
-
-+ }
-+
- nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
- start = dir->u.ext3_i.i_dir_start_lookup;
- if (start >= nblocks)
-@@ -237,6 +748,92 @@
- de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
- }
-
-+static ext3_dirent *
-+dx_copy_dirents (char *from, char *to, struct dx_map_entry *map, int count)
-+{
-+ unsigned rec_len = 0;
-+
-+ while (count--) {
-+ ext3_dirent *de = (ext3_dirent *) (from + map->offs);
-+ rec_len = EXT3_DIR_REC_LEN(de->name_len);
-+ memcpy (to, de, rec_len);
-+ ((ext3_dirent *) to)->rec_len = rec_len;
-+ to += rec_len;
-+ map++;
-+ }
-+ return (ext3_dirent *) (to - rec_len);
-+}
-+
-+#ifdef CONFIG_EXT3_INDEX
-+static ext3_dirent *do_split(handle_t *handle, struct inode *dir,
-+ struct buffer_head **bh,struct dx_frame *frame,
-+ u32 hash, int *error)
-+{
-+ unsigned blocksize = dir->i_sb->s_blocksize;
-+ unsigned count, continued;
-+ struct buffer_head *bh2;
-+ u32 newblock;
-+ unsigned MAX_DX_MAP = PAGE_CACHE_SIZE/EXT3_DIR_REC_LEN(1) + 1;
-+ u32 hash2;
-+ struct dx_map_entry *map;
-+ char *data1 = (*bh)->b_data, *data2, *data3;
-+ unsigned split;
-+ ext3_dirent *de, *de2;
-+
-+ bh2 = ext3_append (handle, dir, &newblock, error);
-+ if (!(bh2))
-+ {
-+ brelse(*bh);
-+ *bh = NULL;
-+ return (ext3_dirent *)bh2;
-+ }
-+
-+ BUFFER_TRACE(*bh, "get_write_access");
-+ ext3_journal_get_write_access(handle, *bh);
-+ BUFFER_TRACE(frame->bh, "get_write_access");
-+ ext3_journal_get_write_access(handle, frame->bh);
-+
-+ data2 = bh2->b_data;
-+
-+ map = kmalloc(sizeof(*map) * MAX_DX_MAP, GFP_KERNEL);
-+ if (!map)
-+ panic("no memory for do_split\n");
-+ count = dx_make_map ((ext3_dirent *) data1, blocksize, map);
-+ split = count/2; // need to adjust to actual middle
-+ dx_sort_map (map, count);
-+ hash2 = map[split].hash;
-+ continued = hash2 == map[split - 1].hash;
-+ dxtrace(printk("Split block %i at %x, %i/%i\n",
-+ dx_get_block(frame->at), hash2, split, count-split));
-+
-+ /* Fancy dance to stay within two buffers */
-+ de2 = dx_copy_dirents (data1, data2, map + split, count - split);
-+ data3 = (char *) de2 + de2->rec_len;
-+ de = dx_copy_dirents (data1, data3, map, split);
-+ memcpy(data1, data3, (char *) de + de->rec_len - data3);
-+ de = (ext3_dirent *) ((char *) de - data3 + data1); // relocate de
-+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-+ de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
-+ dxtrace(dx_show_leaf ((ext3_dirent *) data1, blocksize, 1));
-+ dxtrace(dx_show_leaf ((ext3_dirent *) data2, blocksize, 1));
-+
-+ /* Which block gets the new entry? */
-+ if (hash >= hash2)
-+ {
-+ swap(*bh, bh2);
-+ de = de2;
-+ }
-+ dx_insert_block (frame, hash2 + continued, newblock);
-+ ext3_journal_dirty_metadata (handle, bh2);
-+ brelse (bh2);
-+ ext3_journal_dirty_metadata (handle, frame->bh);
-+ dxtrace(dx_show_index ("frame", frame->entries));
-+ kfree(map);
-+ return de;
-+}
-+#endif
-+
-+
- /*
- * ext3_add_entry()
- *
-@@ -251,6 +844,7 @@
- /*
- * AKPM: the journalling code here looks wrong on the error paths
- */
-+
- static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
- struct inode *inode)
- {
-@@ -258,117 +852,281 @@
- const char *name = dentry->d_name.name;
- int namelen = dentry->d_name.len;
- unsigned long offset;
-- unsigned short rec_len;
- struct buffer_head * bh;
-- struct ext3_dir_entry_2 * de, * de1;
-- struct super_block * sb;
-+ ext3_dirent *de;
-+ struct super_block * sb = dir->i_sb;
- int retval;
-+ unsigned short reclen = EXT3_DIR_REC_LEN(namelen);
-
-- sb = dir->i_sb;
-+ unsigned blocksize = sb->s_blocksize;
-+ unsigned nlen, rlen;
-+ u32 block, blocks;
-+ char *top;
-
- if (!namelen)
- return -EINVAL;
-- bh = ext3_bread (handle, dir, 0, 0, &retval);
-- if (!bh)
-- return retval;
-- rec_len = EXT3_DIR_REC_LEN(namelen);
-- offset = 0;
-- de = (struct ext3_dir_entry_2 *) bh->b_data;
-- while (1) {
-- if ((char *)de >= sb->s_blocksize + bh->b_data) {
-- brelse (bh);
-- bh = NULL;
-- bh = ext3_bread (handle, dir,
-- offset >> EXT3_BLOCK_SIZE_BITS(sb), 1, &retval);
-- if (!bh)
-- return retval;
-- if (dir->i_size <= offset) {
-- if (dir->i_size == 0) {
-- brelse(bh);
-- return -ENOENT;
-+ if (ext3_dx && is_dx(dir)) {
-+ struct dx_frame frames[2], *frame;
-+ struct dx_entry *entries, *at;
-+ u32 hash;
-+ char *data1;
-+
-+ hash = dx_hash(name, namelen);
-+ /* FIXME: do something if dx_probe() fails here */
-+ frame = dx_probe(dir, hash, frames);
-+ entries = frame->entries;
-+ at = frame->at;
-+
-+ if (!(bh = ext3_bread(handle,dir, dx_get_block(at), 0,&retval)))
-+ goto dxfail1;
-+
-+ BUFFER_TRACE(bh, "get_write_access");
-+ ext3_journal_get_write_access(handle, bh);
-+
-+ data1 = bh->b_data;
-+ de = (ext3_dirent *) data1;
-+ top = data1 + (0? 200: blocksize);
-+ while ((char *) de < top)
-+ {
-+ /* FIXME: check EEXIST and dir */
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ if ((de->inode? rlen - nlen: rlen) >= reclen)
-+ goto dx_add;
-+ de = (ext3_dirent *) ((char *) de + rlen);
-+ }
-+ /* Block full, should compress but for now just split */
-+ dxtrace(printk("using %u of %u node entries\n",
-+ dx_get_count(entries), dx_get_limit(entries)));
-+ /* Need to split index? */
-+ if (dx_get_count(entries) == dx_get_limit(entries))
-+ {
-+ u32 newblock;
-+ unsigned icount = dx_get_count(entries);
-+ int levels = frame - frames;
-+ struct dx_entry *entries2;
-+ struct dx_node *node2;
-+ struct buffer_head *bh2;
-+ if (levels && dx_get_count(frames->entries) == dx_get_limit(frames->entries))
-+ goto dxfull;
-+ bh2 = ext3_append (handle, dir, &newblock, &retval);
-+ if (!(bh2))
-+ goto dxfail2;
-+ node2 = (struct dx_node *)(bh2->b_data);
-+ entries2 = node2->entries;
-+ node2->fake.rec_len = cpu_to_le16(blocksize);
-+ node2->fake.inode = 0;
-+ BUFFER_TRACE(frame->bh, "get_write_access");
-+ ext3_journal_get_write_access(handle, frame->bh);
-+ if (levels)
-+ {
-+ unsigned icount1 = icount/2, icount2 = icount - icount1;
-+ unsigned hash2 = dx_get_hash(entries + icount1);
-+ dxtrace(printk("Split index %i/%i\n", icount1, icount2));
-+
-+ BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
-+ ext3_journal_get_write_access(handle, frames[0].bh);
-+
-+ memcpy ((char *) entries2, (char *) (entries + icount1),
-+ icount2 * sizeof(struct dx_entry));
-+ dx_set_count (entries, icount1);
-+ dx_set_count (entries2, icount2);
-+ dx_set_limit (entries2, dx_node_limit(dir));
-+
-+ /* Which index block gets the new entry? */
-+ if (at - entries >= icount1) {
-+ frame->at = at = at - entries - icount1 + entries2;
-+ frame->entries = entries = entries2;
-+ swap(frame->bh, bh2);
- }
--
-- ext3_debug ("creating next block\n");
--
-- BUFFER_TRACE(bh, "get_write_access");
-- ext3_journal_get_write_access(handle, bh);
-- de = (struct ext3_dir_entry_2 *) bh->b_data;
-- de->inode = 0;
-- de->rec_len = le16_to_cpu(sb->s_blocksize);
-- dir->u.ext3_i.i_disksize =
-- dir->i_size = offset + sb->s_blocksize;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-- ext3_mark_inode_dirty(handle, dir);
-+ dx_insert_block (frames + 0, hash2, newblock);
-+ dxtrace(dx_show_index ("node", frames[1].entries));
-+ dxtrace(dx_show_index ("node",
-+ ((struct dx_node *) bh2->b_data)->entries));
-+ ext3_journal_dirty_metadata(handle, bh2);
-+ brelse (bh2);
- } else {
--
-- ext3_debug ("skipping to next block\n");
--
-- de = (struct ext3_dir_entry_2 *) bh->b_data;
-+ dxtrace(printk("Creating second level index...\n"));
-+ memcpy((char *) entries2, (char *) entries,
-+ icount * sizeof(struct dx_entry));
-+ dx_set_limit(entries2, dx_node_limit(dir));
-+
-+ /* Set up root */
-+ dx_set_count(entries, 1);
-+ dx_set_block(entries + 0, newblock);
-+ ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1;
-+
-+ /* Add new access path frame */
-+ frame = frames + 1;
-+ frame->at = at = at - entries + entries2;
-+ frame->entries = entries = entries2;
-+ frame->bh = bh2;
-+ ext3_journal_get_write_access(handle, frame->bh);
- }
-+ ext3_journal_dirty_metadata(handle, frames[0].bh);
- }
-- if (!ext3_check_dir_entry ("ext3_add_entry", dir, de, bh,
-- offset)) {
-- brelse (bh);
-- return -ENOENT;
-- }
-- if (ext3_match (namelen, name, de)) {
-+ de = do_split(handle, dir, &bh, frame, hash, &retval);
-+ dx_release (frames);
-+ if (!(de))
-+ goto fail;
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ goto add;
-+
-+dx_add:
-+ dx_release (frames);
-+ goto add;
-+
-+dxfull:
-+ ext3_warning(sb, __FUNCTION__, "Directory index full!\n");
-+ retval = -ENOSPC;
-+dxfail2:
-+ brelse(bh);
-+dxfail1:
-+ dx_release (frames);
-+ goto fail1;
-+ }
-+
-+ blocks = dir->i_size >> sb->s_blocksize_bits;
-+ for (block = 0, offset = 0; block < blocks; block++) {
-+ bh = ext3_bread(handle, dir, block, 0, &retval);
-+ if(!bh)
-+ return retval;
-+ de = (ext3_dirent *)bh->b_data;
-+ top = bh->b_data + blocksize - reclen;
-+ while ((char *) de <= top) {
-+ if (!ext3_check_dir_entry("ext3_add_entry", dir, de,
-+ bh, offset)) {
-+ brelse (bh);
-+ return -EIO;
-+ }
-+ if (ext3_match (namelen, name, de)) {
- brelse (bh);
- return -EEXIST;
-- }
-- if ((le32_to_cpu(de->inode) == 0 &&
-- le16_to_cpu(de->rec_len) >= rec_len) ||
-- (le16_to_cpu(de->rec_len) >=
-- EXT3_DIR_REC_LEN(de->name_len) + rec_len)) {
-- BUFFER_TRACE(bh, "get_write_access");
-- ext3_journal_get_write_access(handle, bh);
-- /* By now the buffer is marked for journaling */
-- offset += le16_to_cpu(de->rec_len);
-- if (le32_to_cpu(de->inode)) {
-- de1 = (struct ext3_dir_entry_2 *) ((char *) de +
-- EXT3_DIR_REC_LEN(de->name_len));
-- de1->rec_len =
-- cpu_to_le16(le16_to_cpu(de->rec_len) -
-- EXT3_DIR_REC_LEN(de->name_len));
-- de->rec_len = cpu_to_le16(
-- EXT3_DIR_REC_LEN(de->name_len));
-- de = de1;
- }
-- de->file_type = EXT3_FT_UNKNOWN;
-- if (inode) {
-- de->inode = cpu_to_le32(inode->i_ino);
-- ext3_set_de_type(dir->i_sb, de, inode->i_mode);
-- } else
-- de->inode = 0;
-- de->name_len = namelen;
-- memcpy (de->name, name, namelen);
-- /*
-- * XXX shouldn't update any times until successful
-- * completion of syscall, but too many callers depend
-- * on this.
-- *
-- * XXX similarly, too many callers depend on
-- * ext3_new_inode() setting the times, but error
-- * recovery deletes the inode, so the worst that can
-- * happen is that the times are slightly out of date
-- * and/or different from the directory change time.
-- */
-- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-- dir->i_version = ++event;
-- ext3_mark_inode_dirty(handle, dir);
-- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-- ext3_journal_dirty_metadata(handle, bh);
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ if ((de->inode? rlen - nlen: rlen) >= reclen)
-+ goto add;
-+ de = (ext3_dirent *)((char *)de + rlen);
-+ offset += rlen;
-+ }
-+ if (ext3_dx && blocks == 1 && test_opt(sb, INDEX))
-+ goto dx_make_index;
-+ brelse(bh);
-+ }
-+ bh = ext3_append(handle, dir, &block, &retval);
-+ if (!bh)
-+ return retval;
-+ de = (ext3_dirent *) bh->b_data;
-+ de->inode = 0;
-+ de->rec_len = cpu_to_le16(rlen = blocksize);
-+ nlen = 0;
-+ goto add;
-+
-+add:
-+ BUFFER_TRACE(bh, "get_write_access");
-+ ext3_journal_get_write_access(handle, bh);
-+ /* By now the buffer is marked for journaling */
-+ if (de->inode) {
-+ ext3_dirent *de1 = (ext3_dirent *)((char *)de + nlen);
-+ de1->rec_len = cpu_to_le16(rlen - nlen);
-+ de->rec_len = cpu_to_le16(nlen);
-+ de = de1;
-+ }
-+ de->file_type = EXT3_FT_UNKNOWN;
-+ if (inode) {
-+ de->inode = cpu_to_le32(inode->i_ino);
-+ ext3_set_de_type(dir->i_sb, de, inode->i_mode);
-+ } else
-+ de->inode = 0;
-+ de->name_len = namelen;
-+ memcpy (de->name, name, namelen);
-+ /*
-+ * XXX shouldn't update any times until successful
-+ * completion of syscall, but too many callers depend
-+ * on this.
-+ *
-+ * XXX similarly, too many callers depend on
-+ * ext3_new_inode() setting the times, but error
-+ * recovery deletes the inode, so the worst that can
-+ * happen is that the times are slightly out of date
-+ * and/or different from the directory change time.
-+ */
-+ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-+ ext3_update_dx_flag(dir);
-+ dir->i_version = ++event;
-+ ext3_mark_inode_dirty(handle, dir);
-+ BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
-+ ext3_journal_dirty_metadata(handle, bh);
-+ brelse(bh);
-+ return 0;
-+
-+dx_make_index:
-+ {
-+ struct buffer_head *bh2;
-+ struct dx_root *root;
-+ struct dx_frame frames[2], *frame;
-+ struct dx_entry *entries;
-+ ext3_dirent *de2;
-+ char *data1;
-+ unsigned len;
-+ u32 hash;
-+
-+ dxtrace(printk("Creating index\n"));
-+ ext3_journal_get_write_access(handle, bh);
-+ root = (struct dx_root *) bh->b_data;
-+
-+ EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
-+ bh2 = ext3_append (handle, dir, &block, &retval);
-+ if (!(bh2))
-+ {
- brelse(bh);
-- return 0;
-+ return retval;
- }
-- offset += le16_to_cpu(de->rec_len);
-- de = (struct ext3_dir_entry_2 *)
-- ((char *) de + le16_to_cpu(de->rec_len));
-+ data1 = bh2->b_data;
-+
-+ /* The 0th block becomes the root, move the dirents out */
-+ de = (ext3_dirent *) &root->info;
-+ len = ((char *) root) + blocksize - (char *) de;
-+ memcpy (data1, de, len);
-+ de = (ext3_dirent *) data1;
-+ top = data1 + len;
-+ while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top)
-+ de = de2;
-+ de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-+ /* Initialize the root; the dot dirents already exist */
-+ de = (ext3_dirent *) (&root->dotdot);
-+ de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2));
-+ memset (&root->info, 0, sizeof(root->info));
-+ root->info.info_length = sizeof(root->info);
-+ entries = root->entries;
-+ dx_set_block (entries, 1);
-+ dx_set_count (entries, 1);
-+ dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info)));
-+
-+ /* Initialize as for dx_probe */
-+ hash = dx_hash (name, namelen);
-+ frame = frames;
-+ frame->entries = entries;
-+ frame->at = entries;
-+ frame->bh = bh;
-+ bh = bh2;
-+ de = do_split(handle,dir, &bh, frame, hash, &retval);
-+ dx_release (frames);
-+ if (!(de))
-+ return retval;
-+ nlen = EXT3_DIR_REC_LEN(de->name_len);
-+ rlen = le16_to_cpu(de->rec_len);
-+ goto add;
- }
-- brelse (bh);
-- return -ENOSPC;
-+fail1:
-+ return retval;
-+fail:
-+ return -ENOENT;
- }
-
-+
- /*
- * ext3_delete_entry deletes a directory entry by merging it with the
- * previous entry
-@@ -451,7 +1212,8 @@
- struct inode * inode;
- int err;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -478,7 +1240,8 @@
- struct inode *inode;
- int err;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -507,7 +1270,8 @@
- if (dir->i_nlink >= EXT3_LINK_MAX)
- return -EMLINK;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -550,7 +1320,7 @@
- if (err)
- goto out_no_entry;
- dir->i_nlink++;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
- d_instantiate(dentry, inode);
- out_stop:
-@@ -832,7 +1596,7 @@
- ext3_mark_inode_dirty(handle, inode);
- dir->i_nlink--;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
-
- end_rmdir:
-@@ -878,7 +1642,7 @@
- if (retval)
- goto end_unlink;
- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(dir);
- ext3_mark_inode_dirty(handle, dir);
- inode->i_nlink--;
- if (!inode->i_nlink)
-@@ -904,7 +1668,8 @@
- if (l > dir->i_sb->s_blocksize)
- return -ENAMETOOLONG;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5);
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -959,7 +1724,8 @@
- if (inode->i_nlink >= EXT3_LINK_MAX)
- return -EMLINK;
-
-- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS);
-+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -995,7 +1761,8 @@
-
- old_bh = new_bh = dir_bh = NULL;
-
-- handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2);
-+ handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS +
-+ EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
- if (IS_ERR(handle))
- return PTR_ERR(handle);
-
-@@ -1077,7 +1844,7 @@
- new_inode->i_ctime = CURRENT_TIME;
- }
- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
-- old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(old_dir);
- if (dir_bh) {
- BUFFER_TRACE(dir_bh, "get_write_access");
- ext3_journal_get_write_access(handle, dir_bh);
-@@ -1089,7 +1856,7 @@
- new_inode->i_nlink--;
- } else {
- new_dir->i_nlink++;
-- new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-+ ext3_update_dx_flag(new_dir);
- ext3_mark_inode_dirty(handle, new_dir);
- }
- }
---- ./include/linux/ext3_fs.h 2002/03/05 06:18:59 2.1
-+++ ./include/linux/ext3_fs.h 2002/03/05 06:26:56
-@@ -339,6 +339,7 @@
- #define EXT3_MOUNT_WRITEBACK_DATA 0x0C00 /* No data ordering */
- #define EXT3_MOUNT_UPDATE_JOURNAL 0x1000 /* Update the journal format */
- #define EXT3_MOUNT_NO_UID32 0x2000 /* Disable 32-bit UIDs */
-+#define EXT3_MOUNT_INDEX 0x4000 /* Enable directory index */
-
- /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
- #ifndef _LINUX_EXT2_FS_H
-@@ -575,6 +576,24 @@
- #define EXT3_DIR_ROUND (EXT3_DIR_PAD - 1)
- #define EXT3_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT3_DIR_ROUND) & \
- ~EXT3_DIR_ROUND)
-+/*
-+ * Hash Tree Directory indexing
-+ * (c) Daniel Phillips, 2001
-+ */
-+
-+#define CONFIG_EXT3_INDEX
-+
-+#ifdef CONFIG_EXT3_INDEX
-+ enum {ext3_dx = 1};
-+ #define is_dx(dir) (EXT3_I(dir)->i_flags & EXT3_INDEX_FL)
-+#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX)
-+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
-+#else
-+ enum {ext3_dx = 0};
-+ #define is_dx(dir) 0
-+#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX)
-+#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2)
-+#endif
-
- #ifdef __KERNEL__
- /*
---- ./include/linux/ext3_jbd.h 2002/03/05 06:18:59 2.1
-+++ ./include/linux/ext3_jbd.h 2002/03/05 06:33:54
-@@ -63,6 +63,8 @@
-
- #define EXT3_RESERVE_TRANS_BLOCKS 12
-
-+#define EXT3_INDEX_EXTRA_TRANS_BLOCKS 8
-+
- int
- ext3_mark_iloc_dirty(handle_t *handle,
- struct inode *inode,
+++ /dev/null
-Linux Extended Attributes -- Kernel Patch
-24 April 2002, 11:31:18
-
-
-This patch 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 patch 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 patch; if not, write to the Free Software Foundation,
-Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-After extracting the linux-2.4.18.tar.gz package, apply this patch as follows:
-
- cd linux
- patch -p1 < ../linux-2.4.18ea-0.8.26.patch
-
-diff -Nur linux-2.4.18/fs/ext3/ialloc.c linux-2.4.18ea/fs/ext3/ialloc.c
---- linux-2.4.18/fs/ext3/ialloc.c Sun Feb 24 04:42:59 2002
-+++ linux-2.4.18ea/fs/ext3/ialloc.c Sun Feb 24 04:34:43 2002
-@@ -17,6 +17,7 @@
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
- #include <linux/stat.h>
- #include <linux/string.h>
- #include <linux/locks.h>
-@@ -216,6 +217,7 @@
- * as writing the quota to disk may need the lock as well.
- */
- DQUOT_INIT(inode);
-+ ext3_xattr_drop_inode(handle, inode);
- DQUOT_FREE_INODE(inode);
- DQUOT_DROP(inode);
-
-diff -Nur linux-2.4.18/fs/ext3/inode.c linux-2.4.18ea/fs/ext3/inode.c
---- linux-2.4.18/fs/ext3/inode.c Sun Feb 24 04:42:59 2002
-+++ linux-2.4.18ea/fs/ext3/inode.c Thu Mar 14 21:51:59 2002
-@@ -39,6 +39,18 @@
- */
- #undef SEARCH_FROM_ZERO
-
-+/*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static inline int ext3_inode_is_fast_symlink(struct inode *inode)
-+{
-+ int ea_blocks = EXT3_I(inode)->i_file_acl ?
-+ (inode->i_sb->s_blocksize >> 9) : 0;
-+
-+ return (S_ISLNK(inode->i_mode) &&
-+ inode->i_blocks - ea_blocks == 0);
-+}
-+
- /* The ext3 forget function must perform a revoke if we are freeing data
- * which has been journaled. Metadata (eg. indirect blocks) must be
- * revoked in all cases.
-@@ -48,7 +60,7 @@
- * still needs to be revoked.
- */
-
--static int ext3_forget(handle_t *handle, int is_metadata,
-+int ext3_forget(handle_t *handle, int is_metadata,
- struct inode *inode, struct buffer_head *bh,
- int blocknr)
- {
-@@ -164,9 +176,7 @@
- {
- handle_t *handle;
-
-- if (is_bad_inode(inode) ||
-- inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-+ if (is_bad_inode(inode))
- goto no_delete;
-
- lock_kernel();
-@@ -1845,6 +1855,8 @@
- if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
- S_ISLNK(inode->i_mode)))
- return;
-+ if (ext3_inode_is_fast_symlink(inode))
-+ return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
-
-@@ -1992,8 +2004,6 @@
- struct ext3_group_desc * gdp;
-
- if ((inode->i_ino != EXT3_ROOT_INO &&
-- inode->i_ino != EXT3_ACL_IDX_INO &&
-- inode->i_ino != EXT3_ACL_DATA_INO &&
- inode->i_ino != EXT3_JOURNAL_INO &&
- inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
- inode->i_ino > le32_to_cpu(
-@@ -2120,10 +2130,7 @@
-
- brelse (iloc.bh);
-
-- if (inode->i_ino == EXT3_ACL_IDX_INO ||
-- inode->i_ino == EXT3_ACL_DATA_INO)
-- /* Nothing to do */ ;
-- else if (S_ISREG(inode->i_mode)) {
-+ if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
- inode->i_mapping->a_ops = &ext3_aops;
-@@ -2131,7 +2138,7 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
- } else if (S_ISLNK(inode->i_mode)) {
-- if (!inode->i_blocks)
-+ if (ext3_inode_is_fast_symlink(inode))
- inode->i_op = &ext3_fast_symlink_inode_operations;
- else {
- inode->i_op = &page_symlink_inode_operations;
-diff -Nur linux-2.4.18/fs/ext3/namei.c linux-2.4.18ea/fs/ext3/namei.c
---- linux-2.4.18/fs/ext3/namei.c Fri Nov 9 23:25:04 2001
-+++ linux-2.4.18ea/fs/ext3/namei.c Mon Mar 11 03:27:00 2002
-@@ -23,6 +23,7 @@
- #include <linux/sched.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
- #include <linux/fcntl.h>
- #include <linux/stat.h>
- #include <linux/string.h>
-@@ -465,6 +466,8 @@
- inode->i_fop = &extN_file_operations;
- inode->i_mapping->a_ops = &ext3_aops;
- err = ext3_add_nondir(handle, dentry, inode);
-+ if (err)
-+ ext3_xattr_drop_inode(handle, inode);
- ext3_mark_inode_dirty(handle, inode);
- }
- ext3_journal_stop(handle, dir);
-@@ -490,6 +493,8 @@
- if (!IS_ERR(inode)) {
- init_special_inode(inode, mode, rdev);
- err = ext3_add_nondir(handle, dentry, inode);
-+ if (err)
-+ ext3_xattr_drop_inode(handle, inode);
- ext3_mark_inode_dirty(handle, inode);
- }
- ext3_journal_stop(handle, dir);
-@@ -514,7 +519,7 @@
- if (IS_SYNC(dir))
- handle->h_sync = 1;
-
-- inode = ext3_new_inode (handle, dir, S_IFDIR);
-+ inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_stop;
-@@ -522,7 +527,6 @@
- inode->i_op = &ext3_dir_inode_operations;
- inode->i_fop = &ext3_dir_operations;
-- inode->i_size = inode->u.ext3_i.i_disksize = inode->i_sb->s_blocksize;
-- inode->i_blocks = 0;
-+ inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
- dir_block = ext3_bread (handle, inode, 0, 1, &err);
- if (!dir_block) {
- inode->i_nlink--; /* is this nlink == 0? */
-@@ -549,9 +553,6 @@
- BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, dir_block);
- brelse (dir_block);
-- inode->i_mode = S_IFDIR | mode;
-- if (dir->i_mode & S_ISGID)
-- inode->i_mode |= S_ISGID;
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_entry (handle, dentry, inode);
- if (err)
-@@ -565,6 +566,7 @@
- return err;
-
- out_no_entry:
-+ ext3_xattr_drop_inode(handle, inode);
- inode->i_nlink = 0;
- ext3_mark_inode_dirty(handle, inode);
- iput (inode);
-@@ -917,5 +919,5 @@
- goto out_stop;
-
-- if (l > sizeof (inode->u.ext3_i.i_data)) {
-+ if (l > sizeof(EXT3_I(inode)->i_data)) {
- inode->i_op = &page_symlink_inode_operations;
- inode->i_mapping->a_ops = &ext3_aops;
-diff -Nur linux-2.4.18/fs/ext3/super.c linux-2.4.18ea/fs/ext3/super.c
---- linux-2.4.18/fs/ext3/super.c Sun Feb 24 04:42:59 2002
-+++ linux-2.4.18ea/fs/ext3/super.c Thu Apr 4 21:41:05 2002
-@@ -24,6 +24,7 @@
- #include <linux/jbd.h>
- #include <linux/ext3_fs.h>
- #include <linux/ext3_jbd.h>
-+#include <linux/ext3_xattr.h>
- #include <linux/slab.h>
- #include <linux/init.h>
- #include <linux/locks.h>
-@@ -404,6 +405,7 @@
- kdev_t j_dev = sbi->s_journal->j_dev;
- int i;
-
-+ ext3_xattr_put_super(sb);
- journal_destroy(sbi->s_journal);
- if (!(sb->s_flags & MS_RDONLY)) {
- EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-@@ -1734,14 +1772,25 @@
-
- static DECLARE_FSTYPE_DEV(ext3_fs_type, "ext3", ext3_read_super);
-
--static int __init init_ext3_fs(void)
-+static void exit_ext3_fs(void)
- {
-- return register_filesystem(&ext3_fs_type);
-+ unregister_filesystem(&ext3_fs_type);
-+ exit_ext3_xattr_user();
-+ exit_ext3_xattr();
- }
-
--static void __exit exit_ext3_fs(void)
-+static int __init init_ext3_fs(void)
- {
-- unregister_filesystem(&ext3_fs_type);
-+ int error = init_ext3_xattr();
-+ if (!error)
-+ error = init_ext3_xattr_user();
-+ if (!error)
-+ error = register_filesystem(&ext3_fs_type);
-+ if (!error)
-+ return 0;
-+
-+ exit_ext3_fs();
-+ return error;
- }
-
- EXPORT_NO_SYMBOLS;
-diff -Nur linux-2.4.18/fs/ext3/xattr.c linux-2.4.18ea/fs/ext3/xattr.c
---- linux-2.4.18/fs/ext3/xattr.c Thu Jan 1 01:00:00 1970
-+++ linux-2.4.18ea/fs/ext3/xattr.c Wed Apr 3 13:19:05 2002
-@@ -0,0 +1,1247 @@
-+/*
-+ * linux/fs/ext3/xattr.c
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
-+ * Extended attributes for symlinks and special files added per
-+ * suggestion of Luka Renko <luka.renko@hermes.si>.
-+ */
-+
-+/*
-+ * Extended attributes are stored on disk blocks allocated outside of
-+ * any inode. The i_file_acl field is then made to point to this allocated
-+ * block. If all extended attributes of an inode are identical, these
-+ * inodes may share the same extended attribute block. Such situations
-+ * are automatically detected by keeping a cache of recent attribute block
-+ * numbers and hashes over the block's contents in memory.
-+ *
-+ *
-+ * Extended attribute block layout:
-+ *
-+ * +------------------+
-+ * | header |
-+ * ¦ entry 1 | |
-+ * | entry 2 | | growing downwards
-+ * | entry 3 | v
-+ * | four null bytes |
-+ * | . . . |
-+ * | value 1 | ^
-+ * | value 3 | | growing upwards
-+ * | value 2 | |
-+ * +------------------+
-+ *
-+ * The block header is followed by multiple entry descriptors. These entry
-+ * descriptors are variable in size, and alligned to EXT3_XATTR_PAD
-+ * byte boundaries. The entry descriptors are sorted by attribute name,
-+ * so that two extended attribute blocks can be compared efficiently.
-+ *
-+ * Attribute values are aligned to the end of the block, stored in
-+ * no specific order. They are also padded to EXT3_XATTR_PAD byte
-+ * boundaries. No additional gaps are left between them.
-+ *
-+ * Locking strategy
-+ * ----------------
-+ * The VFS already holds the BKL and the inode->i_sem semaphore when any of
-+ * the xattr inode operations are called, so we are guaranteed that only one
-+ * processes accesses extended attributes of an inode at any time.
-+ *
-+ * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
-+ * only a single process is modifying an extended attribute block, even
-+ * if the block is shared among inodes.
-+ *
-+ * Note for porting to 2.5
-+ * -----------------------
-+ * The BKL will no longer be held in the xattr inode operations.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/locks.h>
-+#include <linux/slab.h>
-+#include <linux/ext3_jbd.h>
-+#include <linux/ext3_fs.h>
-+#include <linux/ext3_xattr.h>
-+#ifdef CONFIG_EXT3_FS_XATTR_SHARING
-+#include <linux/mbcache.h>
-+#endif
-+#include <linux/quotaops.h>
-+#include <asm/semaphore.h>
-+#include <linux/compatmac.h>
-+#include <linux/module.h>
-+
-+/* These symbols may be needed by a module. */
-+EXPORT_SYMBOL(extN_xattr_register);
-+EXPORT_SYMBOL(extN_xattr_unregister);
-+EXPORT_SYMBOL(extN_xattr_get);
-+EXPORT_SYMBOL(extN_xattr_list);
-+EXPORT_SYMBOL(extN_xattr_set);
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+# define mark_buffer_dirty(bh) mark_buffer_dirty(bh, 1)
-+#endif
-+
-+#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
-+#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
-+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+
-+#ifdef EXT3_XATTR_DEBUG
-+# define ea_idebug(inode, f...) do { \
-+ printk(KERN_DEBUG "inode %s:%ld: ", \
-+ kdevname(inode->i_dev), inode->i_ino); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+# define ea_bdebug(bh, f...) do { \
-+ printk(KERN_DEBUG "block %s:%ld: ", \
-+ kdevname(bh->b_dev), bh->b_blocknr); \
-+ printk(f); \
-+ printk("\n"); \
-+ } while (0)
-+#else
-+# define ea_idebug(f...)
-+# define ea_bdebug(f...)
-+#endif
-+
-+static int ext3_xattr_set2(handle_t *, struct inode *, struct buffer_head *,
-+ struct ext3_xattr_header *);
-+
-+#ifdef CONFIG_EXT3_FS_XATTR_SHARING
-+
-+static int ext3_xattr_cache_insert(struct buffer_head *);
-+static struct buffer_head *ext3_xattr_cache_find(struct inode *,
-+ struct ext3_xattr_header *);
-+static void ext3_xattr_cache_remove(struct buffer_head *);
-+static void ext3_xattr_rehash(struct ext3_xattr_header *,
-+ struct ext3_xattr_entry *);
-+
-+static struct mb_cache *ext3_xattr_cache;
-+
-+#else
-+# define ext3_xattr_cache_insert(bh) 0
-+# define ext3_xattr_cache_find(inode, header) NULL
-+# define ext3_xattr_cache_remove(bh) do {} while(0)
-+# define ext3_xattr_rehash(header, entry) do {} while(0)
-+#endif
-+
-+/*
-+ * If a file system does not share extended attributes among inodes,
-+ * we should not need the ext3_xattr_sem semaphore. However, the
-+ * filesystem may still contain shared blocks, so we always take
-+ * the lock.
-+ */
-+
-+DECLARE_MUTEX(ext3_xattr_sem);
-+
-+static inline void
-+ext3_xattr_lock(void)
-+{
-+ down(&ext3_xattr_sem);
-+}
-+
-+static inline void
-+ext3_xattr_unlock(void)
-+{
-+ up(&ext3_xattr_sem);
-+}
-+
-+static inline int
-+ext3_xattr_new_block(handle_t *handle, struct inode *inode,
-+ int * errp, int force)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ int goal = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
-+ EXT3_I(inode)->i_block_group * EXT3_BLOCKS_PER_GROUP(sb);
-+
-+ /* How can we enforce the allocation? */
-+ int block = ext3_new_block(handle, inode, goal, 0, 0, errp);
-+#ifdef OLD_QUOTAS
-+ if (!*errp)
-+ inode->i_blocks += inode->i_sb->s_blocksize >> 9;
-+#endif
-+ return block;
-+}
-+
-+static inline int
-+ext3_xattr_quota_alloc(struct inode *inode, int force)
-+{
-+ /* How can we enforce the allocation? */
-+#ifdef OLD_QUOTAS
-+ int error = DQUOT_ALLOC_BLOCK(inode->i_sb, inode, 1);
-+ if (!error)
-+ inode->i_blocks += inode->i_sb->s_blocksize >> 9;
-+#else
-+ int error = DQUOT_ALLOC_BLOCK(inode, 1);
-+#endif
-+ return error;
-+}
-+
-+#ifdef OLD_QUOTAS
-+
-+static inline void
-+ext3_xattr_quota_free(struct inode *inode)
-+{
-+ DQUOT_FREE_BLOCK(inode->i_sb, inode, 1);
-+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
-+}
-+
-+static inline void
-+ext3_xattr_free_block(handle_t *handle, struct inode * inode,
-+ unsigned long block)
-+{
-+ ext3_free_blocks(handle, inode, block, 1);
-+ inode->i_blocks -= inode->i_sb->s_blocksize >> 9;
-+}
-+
-+#else
-+# define ext3_xattr_quota_free(inode) \
-+ DQUOT_FREE_BLOCK(inode, 1)
-+# define ext3_xattr_free_block(handle, inode, block) \
-+ ext3_free_blocks(handle, inode, block, 1)
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
-+
-+static inline struct buffer_head *
-+sb_bread(struct super_block *sb, int block)
-+{
-+ return bread(sb->s_dev, block, sb->s_blocksize);
-+}
-+
-+static inline struct buffer_head *
-+sb_getblk(struct super_block *sb, int block)
-+{
-+ return getblk(sb->s_dev, block, sb->s_blocksize);
-+}
-+
-+#endif
-+
-+struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
-+rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
-+
-+int
-+ext3_xattr_register(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ int error = -EINVAL;
-+
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ if (!ext3_xattr_handlers[name_index-1]) {
-+ ext3_xattr_handlers[name_index-1] = handler;
-+ error = 0;
-+ }
-+ write_unlock(&ext3_handler_lock);
-+ }
-+ return error;
-+}
-+
-+void
-+ext3_xattr_unregister(int name_index, struct ext3_xattr_handler *handler)
-+{
-+ if (name_index > 0 || name_index <= EXT3_XATTR_INDEX_MAX) {
-+ write_lock(&ext3_handler_lock);
-+ ext3_xattr_handlers[name_index-1] = NULL;
-+ write_unlock(&ext3_handler_lock);
-+ }
-+}
-+
-+static inline const char *
-+strcmp_prefix(const char *a, const char *a_prefix)
-+{
-+ while (*a_prefix && *a == *a_prefix) {
-+ a++;
-+ a_prefix++;
-+ }
-+ return *a_prefix ? NULL : a;
-+}
-+
-+/*
-+ * Decode the extended attribute name, and translate it into
-+ * the name_index and name suffix.
-+ */
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_resolve_name(const char **name)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ int i;
-+
-+ if (!*name)
-+ return NULL;
-+ read_lock(&ext3_handler_lock);
-+ for (i=0; i<EXT3_XATTR_INDEX_MAX; i++) {
-+ if (ext3_xattr_handlers[i]) {
-+ const char *n = strcmp_prefix(*name,
-+ ext3_xattr_handlers[i]->prefix);
-+ if (n) {
-+ handler = ext3_xattr_handlers[i];
-+ *name = n;
-+ break;
-+ }
-+ }
-+ }
-+ read_unlock(&ext3_handler_lock);
-+ return handler;
-+}
-+
-+static inline struct ext3_xattr_handler *
-+ext3_xattr_handler(int name_index)
-+{
-+ struct ext3_xattr_handler *handler = NULL;
-+ if (name_index > 0 && name_index <= EXT3_XATTR_INDEX_MAX) {
-+ read_lock(&ext3_handler_lock);
-+ handler = ext3_xattr_handlers[name_index-1];
-+ read_unlock(&ext3_handler_lock);
-+ }
-+ return handler;
-+}
-+
-+/*
-+ * Inode operation getxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+ssize_t
-+ext3_getxattr(struct dentry *dentry, const char *name,
-+ void *buffer, size_t size)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->get(inode, name, buffer, size);
-+}
-+
-+/*
-+ * Inode operation listxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+ssize_t
-+ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+ return ext3_xattr_list(dentry->d_inode, buffer, size);
-+}
-+
-+/*
-+ * Inode operation setxattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+int
-+ext3_setxattr(struct dentry *dentry, const char *name,
-+ void *value, size_t size, int flags)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ if (size == 0)
-+ value = ""; /* empty EA, do not remove */
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->set(inode, name, value, size, flags);
-+}
-+
-+/*
-+ * Inode operation removexattr()
-+ *
-+ * dentry->d_inode->i_sem down
-+ * BKL held [before 2.5.x]
-+ */
-+int
-+ext3_removexattr(struct dentry *dentry, const char *name)
-+{
-+ struct ext3_xattr_handler *handler;
-+ struct inode *inode = dentry->d_inode;
-+
-+ handler = ext3_xattr_resolve_name(&name);
-+ if (!handler)
-+ return -ENOTSUP;
-+ return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
-+}
-+
-+/*
-+ * ext3_xattr_get()
-+ *
-+ * Copy an extended attribute into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size;
-+ char *end;
-+ int name_len, error;
-+
-+ ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
-+ name_index, name, buffer, (long)buffer_size);
-+
-+ if (name == NULL)
-+ return -EINVAL;
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return -ENOATTR;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_get",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* find named attribute */
-+ name_len = strlen(name);
-+
-+ error = -ERANGE;
-+ if (name_len > 255)
-+ goto cleanup;
-+ entry = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (name_index == entry->e_name_index &&
-+ name_len == entry->e_name_len &&
-+ memcmp(name, entry->e_name, name_len) == 0)
-+ goto found;
-+ entry = next;
-+ }
-+ /* Check the remaining name entries */
-+ while (!IS_LAST_ENTRY(entry)) {
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ entry = next;
-+ }
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ error = -ENOATTR;
-+ goto cleanup;
-+found:
-+ /* check the buffer size */
-+ if (entry->e_value_block != 0)
-+ goto bad_block;
-+ size = le32_to_cpu(entry->e_value_size);
-+ if (size > inode->i_sb->s_blocksize ||
-+ le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize)
-+ goto bad_block;
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (buffer) {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ /* return value of attribute */
-+ memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
-+ size);
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_entry *entry;
-+ unsigned int block, size = 0;
-+ char *buf, *end;
-+ int error;
-+
-+ ea_idebug(inode, "buffer=%p, buffer_size=%ld",
-+ buffer, (long)buffer_size);
-+
-+ if (!EXT3_I(inode)->i_file_acl)
-+ return 0;
-+ block = EXT3_I(inode)->i_file_acl;
-+ ea_idebug(inode, "reading block %d", block);
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh)
-+ return -EIO;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
-+ end = bh->b_data + bh->b_size;
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* compute the size required for the list of attribute names */
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+ struct ext3_xattr_entry *next =
-+ EXT3_XATTR_NEXT(entry);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler) {
-+ size += handler->list(NULL, inode, entry->e_name,
-+ entry->e_name_len) + 1;
-+ }
-+ }
-+
-+ if (ext3_xattr_cache_insert(bh))
-+ ea_idebug(inode, "cache insert failed");
-+ if (!buffer) {
-+ error = size;
-+ goto cleanup;
-+ } else {
-+ error = -ERANGE;
-+ if (size > buffer_size)
-+ goto cleanup;
-+ }
-+
-+ /* list the attribute names */
-+ buf = buffer;
-+ for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
-+ entry = EXT3_XATTR_NEXT(entry)) {
-+ struct ext3_xattr_handler *handler;
-+
-+ handler = ext3_xattr_handler(entry->e_name_index);
-+ if (handler) {
-+ buf += handler->list(buf, inode, entry->e_name,
-+ entry->e_name_len);
-+ *buf++ = '\0';
-+ }
-+ }
-+ error = size;
-+
-+cleanup:
-+ brelse(bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * If the EXT3_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-+ * not set, set it.
-+ */
-+static void ext3_xattr_update_super_block(handle_t *handle,
-+ struct super_block *sb)
-+{
-+ if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_EXT_ATTR))
-+ return;
-+
-+ lock_super(sb);
-+ ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-+ EXT3_SB(sb)->s_feature_compat |= EXT3_FEATURE_COMPAT_EXT_ATTR;
-+#endif
-+ EXT3_SB(sb)->s_es->s_feature_compat |=
-+ cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
-+ sb->s_dirt = 1;
-+ ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
-+ unlock_super(sb);
-+}
-+
-+/*
-+ * ext3_xattr_set()
-+ *
-+ * Create, replace or remove an extended attribute for this inode. Buffer
-+ * is NULL to remove an existing extended attribute, and non-NULL to
-+ * either replace an existing extended attribute, or create a new extended
-+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE
-+ * specify that an extended attribute must exist and must not exist
-+ * previous to the call, respectively.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, void *value, size_t value_len, int flags)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *bh = NULL;
-+ struct ext3_xattr_header *header = NULL;
-+ struct ext3_xattr_entry *here, *last;
-+ unsigned int name_len;
-+ int min_offs = sb->s_blocksize, not_found = 1, free, error;
-+ char *end;
-+
-+ /*
-+ * header -- Points either into bh, or to a temporarily
-+ * allocated buffer.
-+ * here -- The named entry found, or the place for inserting, within
-+ * the block pointed to by header.
-+ * last -- Points right after the last named entry within the block
-+ * pointed to by header.
-+ * min_offs -- The offset of the first value (values are aligned
-+ * towards the end of the block).
-+ * end -- Points right after the block pointed to by header.
-+ */
-+
-+ ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+ name_index, name, value, (long)value_len);
-+
-+ if (IS_RDONLY(inode))
-+ return -EROFS;
-+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-+ return -EPERM;
-+ if (value == NULL)
-+ value_len = 0;
-+ if (name == NULL)
-+ return -EINVAL;
-+ name_len = strlen(name);
-+ if (name_len > 255 || value_len > sb->s_blocksize)
-+ return -ERANGE;
-+ ext3_xattr_lock();
-+
-+ if (EXT3_I(inode)->i_file_acl) {
-+ /* The inode already has an extended attribute block. */
-+ int block = EXT3_I(inode)->i_file_acl;
-+
-+ bh = sb_bread(sb, block);
-+ error = -EIO;
-+ if (!bh)
-+ goto cleanup;
-+ ea_bdebug(bh, "b_count=%d, refcount=%d",
-+ atomic_read(&(bh->b_count)),
-+ le32_to_cpu(HDR(bh)->h_refcount));
-+ header = HDR(bh);
-+ end = bh->b_data + bh->b_size;
-+ if (header->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ header->h_blocks != cpu_to_le32(1)) {
-+bad_block: ext3_error(sb, "ext3_xattr_set",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ /* Find the named attribute. */
-+ here = FIRST_ENTRY(bh);
-+ while (!IS_LAST_ENTRY(here)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(here);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!here->e_value_block && here->e_value_size) {
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ not_found = name_index - here->e_name_index;
-+ if (!not_found)
-+ not_found = name_len - here->e_name_len;
-+ if (!not_found)
-+ not_found = memcmp(name, here->e_name,name_len);
-+ if (not_found <= 0)
-+ break;
-+ here = next;
-+ }
-+ last = here;
-+ /* We still need to compute min_offs and last. */
-+ while (!IS_LAST_ENTRY(last)) {
-+ struct ext3_xattr_entry *next = EXT3_XATTR_NEXT(last);
-+ if ((char *)next >= end)
-+ goto bad_block;
-+ if (!last->e_value_block && last->e_value_size) {
-+ int offs = le16_to_cpu(last->e_value_offs);
-+ if (offs < min_offs)
-+ min_offs = offs;
-+ }
-+ last = next;
-+ }
-+
-+ /* Check whether we have enough space left. */
-+ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
-+ } else {
-+ /* We will use a new extended attribute block. */
-+ free = sb->s_blocksize -
-+ sizeof(struct ext3_xattr_header) - sizeof(__u32);
-+ here = last = NULL; /* avoid gcc uninitialized warning. */
-+ }
-+
-+ if (not_found) {
-+ /* Request to remove a nonexistent attribute? */
-+ error = -ENOATTR;
-+ if (flags & XATTR_REPLACE)
-+ goto cleanup;
-+ error = 0;
-+ if (value == NULL)
-+ goto cleanup;
-+ else
-+ free -= EXT3_XATTR_LEN(name_len);
-+ } else {
-+ /* Request to create an existing attribute? */
-+ error = -EEXIST;
-+ if (flags & XATTR_CREATE)
-+ goto cleanup;
-+ if (!here->e_value_block && here->e_value_size) {
-+ unsigned int size = le32_to_cpu(here->e_value_size);
-+
-+ if (le16_to_cpu(here->e_value_offs) + size >
-+ sb->s_blocksize || size > sb->s_blocksize)
-+ goto bad_block;
-+ free += EXT3_XATTR_SIZE(size);
-+ }
-+ }
-+ free -= EXT3_XATTR_SIZE(value_len);
-+ error = -ENOSPC;
-+ if (free < 0)
-+ goto cleanup;
-+
-+ /* Here we know that we can set the new attribute. */
-+
-+ if (header) {
-+ if (header->h_refcount == cpu_to_le32(1)) {
-+ ea_bdebug(bh, "modifying in-place");
-+ ext3_xattr_cache_remove(bh);
-+ error = ext3_journal_get_write_access(handle, bh);
-+ if (error)
-+ goto cleanup;
-+ } else {
-+ int offset;
-+
-+ ea_bdebug(bh, "cloning");
-+ header = kmalloc(bh->b_size, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memcpy(header, HDR(bh), bh->b_size);
-+ header->h_refcount = cpu_to_le32(1);
-+ offset = (char *)header - bh->b_data;
-+ here = ENTRY((char *)here + offset);
-+ last = ENTRY((char *)last + offset);
-+ }
-+ } else {
-+ /* Allocate a buffer where we construct the new block. */
-+ header = kmalloc(sb->s_blocksize, GFP_KERNEL);
-+ error = -ENOMEM;
-+ if (header == NULL)
-+ goto cleanup;
-+ memset(header, 0, sb->s_blocksize);
-+ end = (char *)header + sb->s_blocksize;
-+ header->h_magic = cpu_to_le32(EXT3_XATTR_MAGIC);
-+ header->h_blocks = header->h_refcount = cpu_to_le32(1);
-+ last = here = ENTRY(header+1);
-+ }
-+
-+ if (not_found) {
-+ /* Insert the new name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ int rest = (char *)last - (char *)here;
-+ memmove((char *)here + size, here, rest);
-+ memset(here, 0, size);
-+ here->e_name_index = name_index;
-+ here->e_name_len = name_len;
-+ memcpy(here->e_name, name, name_len);
-+ } else {
-+ /* Remove the old value. */
-+ if (!here->e_value_block && here->e_value_size) {
-+ char *first_val = (char *)header + min_offs;
-+ int offs = le16_to_cpu(here->e_value_offs);
-+ char *val = (char *)header + offs;
-+ size_t size = EXT3_XATTR_SIZE(
-+ le32_to_cpu(here->e_value_size));
-+ memmove(first_val + size, first_val, val - first_val);
-+ memset(first_val, 0, size);
-+ here->e_value_offs = 0;
-+ min_offs += size;
-+
-+ /* Adjust all value offsets. */
-+ last = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(last)) {
-+ int o = le16_to_cpu(last->e_value_offs);
-+ if (!last->e_value_block && o < offs)
-+ last->e_value_offs =
-+ cpu_to_le16(o + size);
-+ last = EXT3_XATTR_NEXT(last);
-+ }
-+ }
-+ if (value == NULL) {
-+ /* Remove this attribute. */
-+ if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
-+ /* This block is now empty. */
-+ error = ext3_xattr_set2(handle, inode, bh,NULL);
-+ goto cleanup;
-+ } else {
-+ /* Remove the old name. */
-+ int size = EXT3_XATTR_LEN(name_len);
-+ last = ENTRY((char *)last - size);
-+ memmove(here, (char*)here + size,
-+ (char*)last - (char*)here);
-+ memset(last, 0, size);
-+ }
-+ }
-+ }
-+
-+ if (value != NULL) {
-+ /* Insert the new value. */
-+ here->e_value_size = cpu_to_le32(value_len);
-+ if (value_len) {
-+ size_t size = EXT3_XATTR_SIZE(value_len);
-+ char *val = (char *)header + min_offs - size;
-+ here->e_value_offs =
-+ cpu_to_le16((char *)val - (char *)header);
-+ memset(val + size - EXT3_XATTR_PAD, 0,
-+ EXT3_XATTR_PAD); /* Clear the pad bytes. */
-+ memcpy(val, value, value_len);
-+ }
-+ }
-+ ext3_xattr_rehash(header, here);
-+
-+ error = ext3_xattr_set2(handle, inode, bh, header);
-+
-+cleanup:
-+ brelse(bh);
-+ if (!(bh && header == HDR(bh)))
-+ kfree(header);
-+ ext3_xattr_unlock();
-+
-+ return error;
-+}
-+
-+/*
-+ * Second half of ext3_xattr_set(): Update the file system.
-+ */
-+static int
-+ext3_xattr_set2(handle_t *handle, struct inode *inode,
-+ struct buffer_head *old_bh, struct ext3_xattr_header *header)
-+{
-+ struct super_block *sb = inode->i_sb;
-+ struct buffer_head *new_bh = NULL;
-+ int error;
-+
-+ if (header) {
-+ new_bh = ext3_xattr_cache_find(inode, header);
-+ if (new_bh) {
-+ /*
-+ * We found an identical block in the cache.
-+ * The old block will be released after updating
-+ * the inode.
-+ */
-+ ea_bdebug(old_bh, "reusing block %ld",
-+ new_bh->b_blocknr);
-+
-+ error = -EDQUOT;
-+ if (ext3_xattr_quota_alloc(inode, 1))
-+ goto cleanup;
-+
-+ error = ext3_journal_get_write_access(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ HDR(new_bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
-+ ea_bdebug(new_bh, "refcount now=%d",
-+ le32_to_cpu(HDR(new_bh)->h_refcount));
-+ } else if (old_bh && header == HDR(old_bh)) {
-+ /* Keep this block. */
-+ new_bh = old_bh;
-+ (void)ext3_xattr_cache_insert(new_bh);
-+ } else {
-+ /* We need to allocate a new block */
-+ int force = EXT3_I(inode)->i_file_acl != 0;
-+ int block = ext3_xattr_new_block(handle, inode,
-+ &error, force);
-+ if (error)
-+ goto cleanup;
-+ ea_idebug(inode, "creating block %d", block);
-+
-+ new_bh = sb_getblk(sb, block);
-+ if (!new_bh) {
-+getblk_failed: ext3_xattr_free_block(handle, inode, block);
-+ error = -EIO;
-+ goto cleanup;
-+ }
-+ lock_buffer(new_bh);
-+ error = ext3_journal_get_create_access(handle, new_bh);
-+ if (error) {
-+ unlock_buffer(new_bh);
-+ goto getblk_failed;
-+ }
-+ memcpy(new_bh->b_data, header, new_bh->b_size);
-+ mark_buffer_uptodate(new_bh, 1);
-+ unlock_buffer(new_bh);
-+ (void)ext3_xattr_cache_insert(new_bh);
-+ ext3_xattr_update_super_block(handle, sb);
-+ }
-+ error = ext3_journal_dirty_metadata(handle, new_bh);
-+ if (error)
-+ goto cleanup;
-+ }
-+
-+ /* Update the inode. */
-+ EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
-+ inode->i_ctime = CURRENT_TIME;
-+ ext3_mark_inode_dirty(handle, inode);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+
-+ error = 0;
-+ if (old_bh && old_bh != new_bh) {
-+ /*
-+ * If there was an old block, and we are not still using it,
-+ * we now release the old block.
-+ */
-+ unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
-+
-+ error = ext3_journal_get_write_access(handle, old_bh);
-+ if (error)
-+ goto cleanup;
-+ if (refcount == 1) {
-+ /* Free the old block. */
-+ ea_bdebug(old_bh, "freeing");
-+ ext3_xattr_free_block(handle, inode, old_bh->b_blocknr);
-+
-+ /* ext3_forget() calls bforget() for us, but we
-+ let our caller release old_bh, so we need to
-+ duplicate the handle before. */
-+ get_bh(old_bh);
-+ ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
-+ } else {
-+ /* Decrement the refcount only. */
-+ refcount--;
-+ HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
-+ ext3_xattr_quota_free(inode);
-+ ext3_journal_dirty_metadata(handle, old_bh);
-+ ea_bdebug(old_bh, "refcount now=%d", refcount);
-+ }
-+ }
-+
-+cleanup:
-+ if (old_bh != new_bh)
-+ brelse(new_bh);
-+
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_drop_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed.
-+ */
-+void
-+ext3_xattr_drop_inode(handle_t *handle, struct inode *inode)
-+{
-+ struct buffer_head *bh;
-+ unsigned int block = EXT3_I(inode)->i_file_acl;
-+
-+ if (!block)
-+ return;
-+ ext3_xattr_lock();
-+
-+ bh = sb_bread(inode->i_sb, block);
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_drop_inode",
-+ "inode %ld: block %d read error", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
-+ if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
-+ HDR(bh)->h_blocks != cpu_to_le32(1)) {
-+ ext3_error(inode->i_sb, "ext3_xattr_drop_inode",
-+ "inode %ld: bad block %d", inode->i_ino, block);
-+ goto cleanup;
-+ }
-+ ext3_journal_get_write_access(handle, bh);
-+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
-+ ext3_xattr_cache_remove(bh);
-+ ext3_xattr_free_block(handle, inode, block);
-+ ext3_forget(handle, 1, inode, bh, block);
-+ bh = NULL;
-+ } else {
-+ HDR(bh)->h_refcount = cpu_to_le32(
-+ le32_to_cpu(HDR(bh)->h_refcount) - 1);
-+ ext3_journal_dirty_metadata(handle, bh);
-+ if (IS_SYNC(inode))
-+ handle->h_sync = 1;
-+ ext3_xattr_quota_free(inode);
-+ }
-+ EXT3_I(inode)->i_file_acl = 0;
-+
-+cleanup:
-+ brelse(bh);
-+ ext3_xattr_unlock();
-+}
-+
-+/*
-+ * ext3_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+#ifdef CONFIG_EXT3_FS_XATTR_SHARING
-+ mb_cache_shrink(ext3_xattr_cache, sb->s_dev);
-+#endif
-+}
-+
-+#ifdef CONFIG_EXT3_FS_XATTR_SHARING
-+
-+/*
-+ * ext3_xattr_cache_insert()
-+ *
-+ * Create a new entry in the extended attribute cache, and insert
-+ * it unless such an entry is already in the cache.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+static int
-+ext3_xattr_cache_insert(struct buffer_head *bh)
-+{
-+ __u32 hash = le32_to_cpu(HDR(bh)->h_hash);
-+ struct mb_cache_entry *ce;
-+ int error;
-+
-+ ce = mb_cache_entry_alloc(ext3_xattr_cache);
-+ if (!ce)
-+ return -ENOMEM;
-+ error = mb_cache_entry_insert(ce, bh->b_dev, bh->b_blocknr, &hash);
-+ if (error) {
-+ mb_cache_entry_free(ce);
-+ if (error == -EBUSY) {
-+ ea_bdebug(bh, "already in cache (%d cache entries)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ error = 0;
-+ }
-+ } else {
-+ ea_bdebug(bh, "inserting [%x] (%d cache entries)", (int)hash,
-+ atomic_read(&ext3_xattr_cache->c_entry_count));
-+ mb_cache_entry_release(ce);
-+ }
-+ return error;
-+}
-+
-+/*
-+ * ext3_xattr_cmp()
-+ *
-+ * Compare two extended attribute blocks for equality.
-+ *
-+ * Returns 0 if the blocks are equal, 1 if they differ, and
-+ * a negative error number on errors.
-+ */
-+static int
-+ext3_xattr_cmp(struct ext3_xattr_header *header1,
-+ struct ext3_xattr_header *header2)
-+{
-+ struct ext3_xattr_entry *entry1, *entry2;
-+
-+ entry1 = ENTRY(header1+1);
-+ entry2 = ENTRY(header2+1);
-+ while (!IS_LAST_ENTRY(entry1)) {
-+ if (IS_LAST_ENTRY(entry2))
-+ return 1;
-+ if (entry1->e_hash != entry2->e_hash ||
-+ entry1->e_name_len != entry2->e_name_len ||
-+ entry1->e_value_size != entry2->e_value_size ||
-+ memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
-+ return 1;
-+ if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
-+ return -EIO;
-+ if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
-+ (char *)header2 + le16_to_cpu(entry2->e_value_offs),
-+ le32_to_cpu(entry1->e_value_size)))
-+ return 1;
-+
-+ entry1 = EXT3_XATTR_NEXT(entry1);
-+ entry2 = EXT3_XATTR_NEXT(entry2);
-+ }
-+ if (!IS_LAST_ENTRY(entry2))
-+ return 1;
-+ return 0;
-+}
-+
-+/*
-+ * ext3_xattr_cache_find()
-+ *
-+ * Find an identical extended attribute block.
-+ *
-+ * Returns a pointer to the block found, or NULL if such a block was
-+ * not found or an error occurred.
-+ */
-+static struct buffer_head *
-+ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
-+{
-+ __u32 hash = le32_to_cpu(header->h_hash);
-+ struct mb_cache_entry *ce;
-+
-+ if (!header->h_hash)
-+ return NULL; /* never share */
-+ ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-+ ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_dev, hash);
-+ while (ce) {
-+ struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
-+
-+ if (!bh) {
-+ ext3_error(inode->i_sb, "ext3_xattr_cache_find",
-+ "inode %ld: block %ld read error",
-+ inode->i_ino, ce->e_block);
-+ } else if (le32_to_cpu(HDR(bh)->h_refcount) >
-+ EXT3_XATTR_REFCOUNT_MAX) {
-+ ea_idebug(inode, "block %ld refcount %d>%d",ce->e_block,
-+ le32_to_cpu(HDR(bh)->h_refcount),
-+ EXT3_XATTR_REFCOUNT_MAX);
-+ } else if (!ext3_xattr_cmp(header, HDR(bh))) {
-+ ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
-+ mb_cache_entry_release(ce);
-+ return bh;
-+ }
-+ brelse(bh);
-+ ce = mb_cache_entry_find_next(ce, 0, inode->i_dev, hash);
-+ }
-+ return NULL;
-+}
-+
-+/*
-+ * ext3_xattr_cache_remove()
-+ *
-+ * Remove the cache entry of a block from the cache. Called when a
-+ * block becomes invalid.
-+ */
-+static void
-+ext3_xattr_cache_remove(struct buffer_head *bh)
-+{
-+ struct mb_cache_entry *ce;
-+
-+ ce = mb_cache_entry_get(ext3_xattr_cache, bh->b_dev, bh->b_blocknr);
-+ if (ce) {
-+ ea_bdebug(bh, "removing (%d cache entries remaining)",
-+ atomic_read(&ext3_xattr_cache->c_entry_count)-1);
-+ mb_cache_entry_free(ce);
-+ } else
-+ ea_bdebug(bh, "no cache entry");
-+}
-+
-+#define NAME_HASH_SHIFT 5
-+#define VALUE_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ __u32 hash = 0;
-+ char *name = entry->e_name;
-+ int n;
-+
-+ for (n=0; n < entry->e_name_len; n++) {
-+ hash = (hash << NAME_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
-+ *name++;
-+ }
-+
-+ if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-+ __u32 *value = (__u32 *)((char *)header +
-+ le16_to_cpu(entry->e_value_offs));
-+ for (n = (le32_to_cpu(entry->e_value_size) +
-+ EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
-+ hash = (hash << VALUE_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
-+ le32_to_cpu(*value++);
-+ }
-+ }
-+ entry->e_hash = cpu_to_le32(hash);
-+}
-+
-+#undef NAME_HASH_SHIFT
-+#undef VALUE_HASH_SHIFT
-+
-+#define BLOCK_HASH_SHIFT 16
-+
-+/*
-+ * ext3_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void ext3_xattr_rehash(struct ext3_xattr_header *header,
-+ struct ext3_xattr_entry *entry)
-+{
-+ struct ext3_xattr_entry *here;
-+ __u32 hash = 0;
-+
-+ ext3_xattr_hash_entry(header, entry);
-+ here = ENTRY(header+1);
-+ while (!IS_LAST_ENTRY(here)) {
-+ if (!here->e_hash) {
-+ /* Block is not shared if an entry's hash value == 0 */
-+ hash = 0;
-+ break;
-+ }
-+ hash = (hash << BLOCK_HASH_SHIFT) ^
-+ (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
-+ le32_to_cpu(here->e_hash);
-+ here = EXT3_XATTR_NEXT(here);
-+ }
-+ header->h_hash = cpu_to_le32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+
-+int __init
-+init_ext3_xattr(void)
-+{
-+ ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
-+ sizeof(struct mb_cache_entry) +
-+ sizeof(struct mb_cache_entry_index), 1, 61);
-+ if (!ext3_xattr_cache)
-+ return -ENOMEM;
-+
-+ return 0;
-+}
-+
-+void
-+exit_ext3_xattr(void)
-+{
-+ if (ext3_xattr_cache)
-+ mb_cache_destroy(ext3_xattr_cache);
-+ ext3_xattr_cache = NULL;
-+}
-+
-+#else /* CONFIG_EXT3_FS_XATTR_SHARING */
-+
-+int __init
-+init_ext3_xattr(void)
-+{
-+ return 0;
-+}
-+
-+void
-+exit_ext3_xattr(void)
-+{
-+}
-+
-+#endif /* CONFIG_EXT3_FS_XATTR_SHARING */
-diff -Nur linux-2.4.18/include/linux/ext3_fs.h linux-2.4.18ea/include/linux/ext3_fs.h
---- linux-2.4.18/include/linux/ext3_fs.h Sun Feb 24 04:42:59 2002
-+++ linux-2.4.18ea/include/linux/ext3_fs.h Mon Mar 11 03:27:00 2002
-@@ -58,8 +58,6 @@
- */
- #define EXT3_BAD_INO 1 /* Bad blocks inode */
- #define EXT3_ROOT_INO 2 /* Root inode */
--#define EXT3_ACL_IDX_INO 3 /* ACL inode */
--#define EXT3_ACL_DATA_INO 4 /* ACL inode */
- #define EXT3_BOOT_LOADER_INO 5 /* Boot loader inode */
- #define EXT3_UNDEL_DIR_INO 6 /* Undelete directory inode */
- #define EXT3_RESIZE_INO 7 /* Reserved group descriptors inode */
-@@ -89,7 +87,6 @@
- #else
- # define EXT3_BLOCK_SIZE(s) (EXT3_MIN_BLOCK_SIZE << (s)->s_log_block_size)
- #endif
--#define EXT3_ACLE_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (struct ext3_acl_entry))
- #define EXT3_ADDR_PER_BLOCK(s) (EXT3_BLOCK_SIZE(s) / sizeof (__u32))
- #ifdef __KERNEL__
- # define EXT3_BLOCK_SIZE_BITS(s) ((s)->s_blocksize_bits)
-@@ -124,28 +121,6 @@
- #endif
-
- /*
-- * ACL structures
-- */
--struct ext3_acl_header /* Header of Access Control Lists */
--{
-- __u32 aclh_size;
-- __u32 aclh_file_count;
-- __u32 aclh_acle_count;
-- __u32 aclh_first_acle;
--};
--
--struct ext3_acl_entry /* Access Control List Entry */
--{
-- __u32 acle_size;
-- __u16 acle_perms; /* Access permissions */
-- __u16 acle_type; /* Type of entry */
-- __u16 acle_tag; /* User or group identity */
-- __u16 acle_pad1;
-- __u32 acle_next; /* Pointer on next entry for the */
-- /* same inode or on next free entry */
--};
--
--/*
- * Structure of a blocks group descriptor
- */
- struct ext3_group_desc
-@@ -512,7 +487,7 @@
- #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
- #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */
-
--#define EXT3_FEATURE_COMPAT_SUPP 0
-+#define EXT3_FEATURE_COMPAT_SUPP EXT3_FEATURE_COMPAT_EXT_ATTR
- #define EXT3_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_FILETYPE| \
- EXT3_FEATURE_INCOMPAT_RECOVER)
- #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
-@@ -603,4 +578,22 @@
- */
-
-+/* Defined for extended attributes */
-+#define CONFIG_EXT3_FS_XATTR y
-+#ifndef ENOATTR
-+#define ENOATTR ENODATA /* No such attribute */
-+#endif
-+#ifndef ENOTSUP
-+#define ENOTSUP EOPNOTSUPP /* Operation not supported */
-+#endif
-+#ifndef XATTR_NAME_MAX
-+#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */
-+#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */
-+#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */
-+#endif
-+#ifndef XATTR_CREATE
-+#define XATTR_CREATE 1 /* set value, fail if attr already exists */
-+#define XATTR_REPLACE 2 /* set value, fail if attr does not exist */
-+#endif
-+
- /*
- * Ok, these declarations are also in <linux/kernel.h> but none of the
-@@ -628,6 +603,7 @@
- extern unsigned long ext3_count_free (struct buffer_head *, unsigned);
-
- /* inode.c */
-+extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
- extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
- extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
-
-diff -Nur linux-2.4.18/include/linux/ext3_jbd.h linux-2.4.18ea/include/linux/ext3_jbd.h
---- linux-2.4.18/include/linux/ext3_jbd.h Fri Dec 21 18:42:03 2001
-+++ linux-2.4.18ea/include/linux/ext3_jbd.h Mon Mar 25 00:11:36 2002
-@@ -30,13 +30,19 @@
-
- #define EXT3_SINGLEDATA_TRANS_BLOCKS 8
-
-+/* Extended attributes may touch two data buffers, two bitmap buffers,
-+ * and two group and summaries. */
-+
-+#define EXT3_XATTR_TRANS_BLOCKS 8
-+
- /* Define the minimum size for a transaction which modifies data. This
- * needs to take into account the fact that we may end up modifying two
- * quota files too (one for the group, one for the user quota). The
- * superblock only gets updated once, of course, so don't bother
- * counting that again for the quota updates. */
-
--#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS - 2)
-+#define EXT3_DATA_TRANS_BLOCKS (3 * EXT3_SINGLEDATA_TRANS_BLOCKS + \
-+ EXT3_XATTR_TRANS_BLOCKS - 2)
-
- extern int ext3_writepage_trans_blocks(struct inode *inode);
-
-diff -Nur linux-2.4.18/include/linux/ext3_xattr.h linux-2.4.18ea/include/linux/ext3_xattr.h
---- linux-2.4.18/include/linux/ext3_xattr.h Thu Jan 1 01:00:00 1970
-+++ linux-2.4.18ea/include/linux/ext3_xattr.h Fri Apr 5 10:08:01 2002
-@@ -0,0 +1,155 @@
-+/*
-+ File: linux/ext3_xattr.h
-+
-+ On-disk format of extended attributes for the ext3 filesystem.
-+
-+ (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+#include <linux/config.h>
-+#include <linux/init.h>
-+#include <linux/xattr.h>
-+
-+/* Magic value in attribute blocks */
-+#define EXT3_XATTR_MAGIC 0xEA020000
-+
-+/* Maximum number of references to one attribute block */
-+#define EXT3_XATTR_REFCOUNT_MAX 1024
-+
-+/* Name indexes */
-+#define EXT3_XATTR_INDEX_MAX 10
-+#define EXT3_XATTR_INDEX_USER 1
-+
-+struct ext3_xattr_header {
-+ __u32 h_magic; /* magic number for identification */
-+ __u32 h_refcount; /* reference count */
-+ __u32 h_blocks; /* number of disk blocks used */
-+ __u32 h_hash; /* hash value of all attributes */
-+ __u32 h_reserved[4]; /* zero right now */
-+};
-+
-+struct ext3_xattr_entry {
-+ __u8 e_name_len; /* length of name */
-+ __u8 e_name_index; /* attribute name index */
-+ __u16 e_value_offs; /* offset in disk block of value */
-+ __u32 e_value_block; /* disk block attribute is stored on (n/i) */
-+ __u32 e_value_size; /* size of attribute value */
-+ __u32 e_hash; /* hash value of name and value */
-+ char e_name[0]; /* attribute name */
-+};
-+
-+#define EXT3_XATTR_PAD_BITS 2
-+#define EXT3_XATTR_PAD (1<<EXT3_XATTR_PAD_BITS)
-+#define EXT3_XATTR_ROUND (EXT3_XATTR_PAD-1)
-+#define EXT3_XATTR_LEN(name_len) \
-+ (((name_len) + EXT3_XATTR_ROUND + \
-+ sizeof(struct ext3_xattr_entry)) & ~EXT3_XATTR_ROUND)
-+#define EXT3_XATTR_NEXT(entry) \
-+ ( (struct ext3_xattr_entry *)( \
-+ (char *)(entry) + EXT3_XATTR_LEN((entry)->e_name_len)) )
-+#define EXT3_XATTR_SIZE(size) \
-+ (((size) + EXT3_XATTR_ROUND) & ~EXT3_XATTR_ROUND)
-+
-+#ifdef __KERNEL__
-+
-+# ifdef CONFIG_EXT3_FS_XATTR
-+
-+struct ext3_xattr_handler {
-+ char *prefix;
-+ size_t (*list)(char *list, struct inode *inode, const char *name,
-+ int name_len);
-+ int (*get)(struct inode *inode, const char *name, void *buffer,
-+ size_t size);
-+ int (*set)(struct inode *inode, const char *name, void *buffer,
-+ size_t size, int flags);
-+};
-+
-+extern int ext3_xattr_register(int, struct ext3_xattr_handler *);
-+extern void ext3_xattr_unregister(int, struct ext3_xattr_handler *);
-+
-+extern int ext3_setxattr(struct dentry *, const char *, void *, size_t, int);
-+extern ssize_t ext3_getxattr(struct dentry *, const char *, void *, size_t);
-+extern ssize_t ext3_listxattr(struct dentry *, char *, size_t);
-+extern int ext3_removexattr(struct dentry *, const char *);
-+
-+extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int ext3_xattr_list(struct inode *, char *, size_t);
-+extern int ext3_xattr_set(handle_t *handle, struct inode *, int, const char *, void *, size_t, int);
-+
-+extern void ext3_xattr_drop_inode(handle_t *, struct inode *);
-+extern void ext3_xattr_put_super(struct super_block *);
-+
-+extern int init_ext3_xattr(void) __init;
-+extern void exit_ext3_xattr(void);
-+
-+# else /* CONFIG_EXT3_FS_XATTR */
-+# define ext3_setxattr NULL
-+# define ext3_getxattr NULL
-+# define ext3_listxattr NULL
-+# define ext3_removexattr NULL
-+
-+static inline int
-+ext3_xattr_get(struct inode *inode, int name_index, const char *name,
-+ void *buffer, size_t size, int flags)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext3_xattr_list(struct inode *inode, void *buffer, size_t size, int flags)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline int
-+ext3_xattr_set(handle_t *handle, struct inode *inode, int name_index,
-+ const char *name, void *value, size_t size, int flags)
-+{
-+ return -ENOTSUP;
-+}
-+
-+static inline void
-+ext3_xattr_drop_inode(handle_t *handle, struct inode *inode)
-+{
-+}
-+
-+static inline void
-+ext3_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_ext3_xattr(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext3_xattr(void)
-+{
-+}
-+
-+# endif /* CONFIG_EXT3_FS_XATTR */
-+
-+# ifdef CONFIG_EXT3_FS_XATTR_USER
-+
-+extern int init_ext3_xattr_user(void) __init;
-+extern void exit_ext3_xattr_user(void);
-+
-+# else /* CONFIG_EXT3_FS_XATTR_USER */
-+
-+static inline int
-+init_ext3_xattr_user(void)
-+{
-+ return 0;
-+}
-+
-+static inline void
-+exit_ext3_xattr_user(void)
-+{
-+}
-+
-+#endif /* CONFIG_EXT3_FS_XATTR_USER */
-+
-+#endif /* __KERNEL__ */
-+
-diff -Nur linux-2.4.18/include/linux/xattr.h linux-2.4.18ea/include/linux/xattr.h
---- linux-2.4.18/include/linux/xattr.h Thu Jan 1 01:00:00 1970
-+++ linux-2.4.18ea/include/linux/xattr.h Sun Mar 24 23:42:21 2002
-@@ -0,0 +1,15 @@
-+/*
-+ File: linux/xattr.h
-+
-+ Extended attributes handling.
-+
-+ Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
-+ Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
-+*/
-+#ifndef _LINUX_XATTR_H
-+#define _LINUX_XATTR_H
-+
-+#define XATTR_CREATE 1 /* set value, fail if attr already exists */
-+#define XATTR_REPLACE 2 /* set value, fail if attr does not exist */
-+
-+#endif /* _LINUX_XATTR_H */
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-config.h
-stamp-h
-stamp-h.in
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
-/* include/config.h.in. Generated automatically from configure.in by autoheader. */
-
-/* Define if you have the `readline' library (-lreadline). */
-#undef HAVE_LIBREADLINE
-
-/* Name of package */
-#undef PACKAGE
-
-/* Version number of package */
-#undef VERSION
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
-extN_fs.h
-extN_fs_i.h
-extN_fs_sb.h
-extN_jbd.h
-extN_xattr.h
-xattr.h
-lustre_build_version.h
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-all .DEFAULT:
- $(MAKE) -C ../.. $@
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Top level header file for LProc SNMP
- * Author: Hariharan Thantry thantry@users.sourceforge.net
- */
-#ifndef _LPROCFS_SNMP_H
-#define _LPROCFS_SNMP_H
-
-
-#ifndef LPROC_SNMP
-#define LPROC_SNMP
-#endif
-
-#include <linux/proc_fs.h>
-
-typedef enum {
- E_LPROC_OK = 0
-} lproc_error_t;
-
-struct lprocfs_vars{
-
- char* name;
- read_proc_t* read_fptr;
- write_proc_t* write_fptr;
- void* data;
-};
-
-#ifdef LPROC_SNMP
-
-struct proc_dir_entry* lprocfs_mkdir(const char *dname,
- struct proc_dir_entry *parent);
-struct proc_dir_entry* lprocfs_srch(struct proc_dir_entry *head,
- const char *name);
-void lprocfs_remove_all(struct proc_dir_entry *root);
-struct proc_dir_entry* lprocfs_new_dir(struct proc_dir_entry *root,
- const char *string,
- const char *tok);
-int lprocfs_new_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
- const char *tok, void *data);
-
-int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *var,
- void *data);
-int lprocfs_reg_obd(struct obd_device *device, struct lprocfs_vars *list,
- void *data);
-int lprocfs_dereg_obd(struct obd_device *device);
-struct proc_dir_entry* lprocfs_reg_mnt(char *mnt_name);
-int lprocfs_dereg_mnt(struct proc_dir_entry *root);
-
-int lprocfs_reg_class(struct obd_type *type, struct lprocfs_vars *list,
- void *data);
-int lprocfs_dereg_class(struct obd_type *class);
-int lprocfs_reg_main(void);
-int lprocfs_dereg_main(void);
-int lprocfs_ll_rd(char *page, char **start, off_t off, int count, int *eof,
- void *data);
-#else
-
-
-static inline int lprocfs_add_vars(struct proc_dir_entry *root,
- struct lprocfs_vars *var, void *data)
-{
- return 0;
-}
-
-static inline int lprocfs_reg_obd(struct obd_device* device,
- struct lprocfs_vars* list, void* data)
-{
- return 0;
-}
-
-static inline int lprocfs_dereg_obd(struct obd_device* device)
-{
- return 0;
-}
-
-static inline struct proc_dir_entry* lprocfs_reg_mnt(char *name)
-{
- return NULL;
-}
-
-static inline int lprocfs_dereg_mnt(struct proc_dir_entry* root)
-{
- return 0;
-}
-
-static inline int lprocfs_reg_class(struct obd_type* type,
- struct lprocfs_vars* list, void* data)
-{
- return 0;
-}
-
-static inline int lprocfs_dereg_class(struct obd_type* class)
-{
- return 0;
-}
-
-static inline int lprocfs_reg_main(void)
-{
- return 0;
-}
-
-static inline int lprocfs_dereg_main(void)
-{
- return 0;
-}
-
-static inline int lprocfs_ll_rd(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- return 0;
-}
-#endif /* LPROC_SNMP */
-
-#endif /* LPROCFS_SNMP_H */
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef _LUSTRE_DEBUG_H
-#define _LUSTRE_DEBUG_H
-
-#include <linux/lustre_net.h>
-
-#define ASSERT_MAX_SIZE_MB 60000ULL
-#define ASSERT_PAGE_INDEX(index, OP) \
-do { if (index > ASSERT_MAX_SIZE_MB << (20 - PAGE_SHIFT)) { \
- CERROR("bad page index %lu > %Lu\n", index, \
- ASSERT_MAX_SIZE_MB << (20 - PAGE_SHIFT)); \
- portal_debug = ~0UL; \
- OP; \
-}} while(0)
-
-#define ASSERT_FILE_OFFSET(offset, OP) \
-do { if (offset > ASSERT_MAX_SIZE_MB << 20) { \
- CERROR("bad file offset %Lu > %Lu\n", offset, \
- ASSERT_MAX_SIZE_MB << 20); \
- portal_debug = ~0UL; \
- OP; \
-}} while(0)
-
-/* lib/debug.c */
-int dump_lniobuf(struct niobuf_local *lnb);
-int dump_rniobuf(struct niobuf_remote *rnb);
-int dump_ioo(struct obd_ioobj *nb);
-int dump_req(struct ptlrpc_request *req);
-int dump_obdo(struct obdo *oa);
-int page_debug_setup(void *addr, int len, __u64 off, __u64 id);
-int page_debug_check(char *who, void *addr, int len, __u64 off, __u64 id);
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * (visit-tags-table FILE)
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-
-#ifndef _LUSTRE_DLM_H__
-#define _LUSTRE_DLM_H__
-
-#ifdef __KERNEL__
-
-#include <linux/proc_fs.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_net.h>
-#include <linux/lustre_import.h>
-
-struct obd_ops;
-struct obd_device;
-
-#define OBD_LDLM_DEVICENAME "ldlm"
-
-typedef enum {
- ELDLM_OK = 0,
-
- ELDLM_LOCK_CHANGED = 300,
- ELDLM_LOCK_ABORTED = 301,
-
- ELDLM_NAMESPACE_EXISTS = 400,
- ELDLM_BAD_NAMESPACE = 401
-} ldlm_error_t;
-
-#define LDLM_NAMESPACE_SERVER 0
-#define LDLM_NAMESPACE_CLIENT 1
-
-#define LDLM_FL_LOCK_CHANGED (1 << 0) /* extent, mode, or resource changed */
-
-/* If the server returns one of these flags, then the lock was put on that list.
- * If the client sends one of these flags (during recovery ONLY!), it wants the
- * lock added to the specified list, no questions asked. -p */
-#define LDLM_FL_BLOCK_GRANTED (1 << 1)
-#define LDLM_FL_BLOCK_CONV (1 << 2)
-#define LDLM_FL_BLOCK_WAIT (1 << 3)
-
-#define LDLM_FL_CBPENDING (1 << 4) // this lock is being destroyed
-#define LDLM_FL_AST_SENT (1 << 5) // blocking or cancel packet was sent
-#define LDLM_FL_WAIT_NOREPROC (1 << 6)// not a real lock flag,not saved in lock
-#define LDLM_FL_CANCEL (1 << 7) // cancellation callback already run
-
-/* Lock is being replayed. This could probably be implied by the fact that one
- * of BLOCK_{GRANTED,CONV,WAIT} is set, but that is pretty dangerous. */
-#define LDLM_FL_REPLAY (1 << 8)
-
-#define LDLM_FL_INTENT_ONLY (1 << 9) /* don't grant lock, just do intent */
-#define LDLM_FL_LOCAL_ONLY (1 << 10) /* see ldlm_cli_cancel_unused */
-#define LDLM_FL_NO_CALLBACK (1 << 11) /* see ldlm_cli_cancel_unused */
-#define LDLM_FL_HAS_INTENT (1 << 12) /* lock request has intent */
-#define LDLM_FL_CANCELING (1 << 13) /* lock cancel has already been sent */
-
-/* The blocking callback is overloaded to perform two functions. These flags
- * indicate which operation should be performed. */
-#define LDLM_CB_BLOCKING 1
-#define LDLM_CB_CANCELING 2
-
-#define L2B(c) (1 << c)
-
-/* compatibility matrix */
-#define LCK_COMPAT_EX L2B(LCK_NL)
-#define LCK_COMPAT_PW (LCK_COMPAT_EX | L2B(LCK_CR))
-#define LCK_COMPAT_PR (LCK_COMPAT_PW | L2B(LCK_PR))
-#define LCK_COMPAT_CW (LCK_COMPAT_PW | L2B(LCK_CW))
-#define LCK_COMPAT_CR (LCK_COMPAT_CW | L2B(LCK_PR) | L2B(LCK_PW))
-#define LCK_COMPAT_NL (LCK_COMPAT_CR | L2B(LCK_EX))
-
-static ldlm_mode_t lck_compat_array[] = {
- [LCK_EX] LCK_COMPAT_EX,
- [LCK_PW] LCK_COMPAT_PW,
- [LCK_PR] LCK_COMPAT_PR,
- [LCK_CW] LCK_COMPAT_CW,
- [LCK_CR] LCK_COMPAT_CR,
- [LCK_NL] LCK_COMPAT_NL
-};
-
-static inline int lockmode_compat(ldlm_mode_t exist, ldlm_mode_t new)
-{
- if (exist < LCK_EX || exist > LCK_NL)
- LBUG();
- if (new < LCK_EX || new > LCK_NL)
- LBUG();
-
- return (lck_compat_array[exist] & L2B(new));
-}
-
-/*
- *
- * cluster name spaces
- *
- */
-
-#define DLM_OST_NAMESPACE 1
-#define DLM_MDS_NAMESPACE 2
-
-/* XXX
- - do we just separate this by security domains and use a prefix for
- multiple namespaces in the same domain?
- -
-*/
-
-struct ldlm_namespace {
- char *ns_name;
- __u32 ns_client; /* is this a client-side lock tree? */
- struct list_head *ns_hash; /* hash table for ns */
- __u32 ns_refcount; /* count of resources in the hash */
- struct list_head ns_root_list; /* all root resources in ns */
- struct lustre_lock ns_lock; /* protects hash, refcount, list */
- struct list_head ns_list_chain; /* position in global NS list */
- /*
- struct proc_dir_entry *ns_proc_dir;
- */
-
- struct list_head ns_unused_list; /* all root resources in ns */
- unsigned int ns_nr_unused;
- unsigned int ns_max_unused;
-
- spinlock_t ns_counter_lock;
- __u64 ns_locks;
- __u64 ns_resources;
-};
-
-/*
- *
- * Resource hash table
- *
- */
-
-#define RES_HASH_BITS 14
-#define RES_HASH_SIZE (1UL << RES_HASH_BITS)
-#define RES_HASH_MASK (RES_HASH_SIZE - 1)
-
-struct ldlm_lock;
-
-typedef int (*ldlm_blocking_callback)(struct ldlm_lock *lock,
- struct ldlm_lock_desc *new, void *data,
- __u32 data_len, int flag);
-
-typedef int (*ldlm_completion_callback)(struct ldlm_lock *lock, int flags);
-
-struct ldlm_lock {
- __u64 l_random;
- atomic_t l_refc;
- struct ldlm_resource *l_resource;
- struct ldlm_lock *l_parent;
- struct list_head l_children;
- struct list_head l_childof;
- struct list_head l_lru;
- struct list_head l_res_link; /*position in one of three res lists*/
- struct list_head l_export_chain; /* per-export chain of locks */
- struct list_head l_pending_chain; /* locks with callbacks pending*/
- unsigned long l_callback_timeout;
-
- ldlm_mode_t l_req_mode;
- ldlm_mode_t l_granted_mode;
-
- ldlm_completion_callback l_completion_ast;
- ldlm_blocking_callback l_blocking_ast;
-
- struct obd_export *l_export;
- struct lustre_handle *l_connh;
- __u32 l_flags;
- struct lustre_handle l_remote_handle;
- void *l_data;
- __u32 l_data_len;
- struct ldlm_extent l_extent;
- __u32 l_version[RES_VERSION_SIZE];
-
- __u32 l_readers;
- __u32 l_writers;
- __u8 l_destroyed;
-
- /* If the lock is granted, a process sleeps on this waitq to learn when
- * it's no longer in use. If the lock is not granted, a process sleeps
- * on this waitq to learn when it becomes granted. */
- wait_queue_head_t l_waitq;
-};
-
-typedef int (*ldlm_res_compat)(struct ldlm_lock *child, struct ldlm_lock *new);
-typedef int (*ldlm_res_policy)(struct ldlm_lock *lock, void *req_cookie,
- ldlm_mode_t mode, int flags, void *data);
-
-#define LDLM_PLAIN 10
-#define LDLM_EXTENT 11
-
-#define LDLM_MIN_TYPE 10
-#define LDLM_MAX_TYPE 11
-
-extern ldlm_res_compat ldlm_res_compat_table [];
-extern ldlm_res_policy ldlm_res_policy_table [];
-
-struct ldlm_resource {
- struct ldlm_namespace *lr_namespace;
- struct list_head lr_hash;
- struct ldlm_resource *lr_parent; /* 0 for a root resource */
- struct list_head lr_children; /* list head for child resources */
- struct list_head lr_childof; /* part of ns_root_list if root res,
- * part of lr_children if child */
-
- struct list_head lr_granted;
- struct list_head lr_converting;
- struct list_head lr_waiting;
- ldlm_mode_t lr_most_restr;
- __u32 lr_type; /* LDLM_PLAIN or LDLM_EXTENT */
- struct ldlm_resource *lr_root;
- __u64 lr_name[RES_NAME_SIZE];
- __u32 lr_version[RES_VERSION_SIZE];
- atomic_t lr_refcount;
- void *lr_tmp;
-};
-
-struct ldlm_ast_work {
- struct ldlm_lock *w_lock;
- int w_blocking;
- struct ldlm_lock_desc w_desc;
- struct list_head w_list;
- int w_flags;
- void *w_data;
- int w_datalen;
-};
-
-/* Per-export ldlm state. */
-struct ldlm_export_data {
- struct list_head led_held_locks;
- struct obd_import led_import;
-};
-
-static inline struct ldlm_extent *ldlm_res2extent(struct ldlm_resource *res)
-{
- return (struct ldlm_extent *)(res->lr_name);
-}
-
-extern struct obd_ops ldlm_obd_ops;
-
-extern char *ldlm_lockname[];
-extern char *ldlm_typename[];
-extern char *ldlm_it2str(int it);
-
-#define LDLM_DEBUG(lock, format, a...) \
-do { \
- if (lock->l_resource == NULL) { \
- CDEBUG(D_DLMTRACE, "### " format \
- " ns: \?\? lock: %p lrc: %d/%d,%d mode: %s/%s " \
- "res: \?\? rrc=\?\? type: \?\?\? remote: "LPX64")\n" \
- , ## a, lock, lock->l_refc, lock->l_readers, \
- lock->l_writers, \
- ldlm_lockname[lock->l_granted_mode], \
- ldlm_lockname[lock->l_req_mode], \
- lock->l_remote_handle.addr); \
- break; \
- } \
- if (lock->l_resource->lr_type == LDLM_EXTENT) { \
- CDEBUG(D_DLMTRACE, "### " format \
- " ns: %s lock: %p lrc: %d/%d,%d mode: %s/%s res: "LPU64 \
- "/"LPU64" rrc: %d type: %s ["LPU64"->"LPU64"] remote: " \
- LPX64"\n" , ## a, \
- lock->l_resource->lr_namespace->ns_name, lock, \
- lock->l_refc, lock->l_readers, lock->l_writers, \
- ldlm_lockname[lock->l_granted_mode], \
- ldlm_lockname[lock->l_req_mode], \
- lock->l_resource->lr_name[0], \
- lock->l_resource->lr_name[1], \
- atomic_read(&lock->l_resource->lr_refcount), \
- ldlm_typename[lock->l_resource->lr_type], \
- lock->l_extent.start, lock->l_extent.end, \
- lock->l_remote_handle.addr); \
- break; \
- } \
- { \
- CDEBUG(D_DLMTRACE, "### " format \
- " ns: %s lock: %p lrc: %d/%d,%d mode: %s/%s res: "LPU64 \
- "/"LPU64" rrc: %d type: %s remote: "LPX64"\n" , ## a, \
- lock->l_resource->lr_namespace->ns_name, lock, \
- lock->l_refc, lock->l_readers, lock->l_writers, \
- ldlm_lockname[lock->l_granted_mode], \
- ldlm_lockname[lock->l_req_mode], \
- lock->l_resource->lr_name[0], \
- lock->l_resource->lr_name[1], \
- atomic_read(&lock->l_resource->lr_refcount), \
- ldlm_typename[lock->l_resource->lr_type], \
- lock->l_remote_handle.addr); \
- } \
-} while (0)
-
-#define LDLM_DEBUG_NOLOCK(format, a...) \
- CDEBUG(D_DLMTRACE, "### " format "\n" , ## a)
-
-/*
- * Iterators.
- */
-
-#define LDLM_ITER_CONTINUE 0 /* keep iterating */
-#define LDLM_ITER_STOP 1 /* stop iterating */
-
-typedef int (*ldlm_iterator_t)(struct ldlm_lock *, void *);
-
-int ldlm_resource_foreach(struct ldlm_resource *res, ldlm_iterator_t iter,
- void *closure);
-int ldlm_namespace_foreach(struct ldlm_namespace *ns, ldlm_iterator_t iter,
- void *closure);
-
-int ldlm_replay_locks(struct obd_import *imp);
-
-/* ldlm_extent.c */
-int ldlm_extent_compat(struct ldlm_lock *, struct ldlm_lock *);
-int ldlm_extent_policy(struct ldlm_lock *, void *, ldlm_mode_t, int flags,
- void *);
-
-/* ldlm_lockd.c */
-int ldlm_handle_enqueue(struct ptlrpc_request *req);
-int ldlm_handle_convert(struct ptlrpc_request *req);
-int ldlm_handle_cancel(struct ptlrpc_request *req);
-int ldlm_del_waiting_lock(struct ldlm_lock *lock);
-
-/* ldlm_lock.c */
-void ldlm_register_intent(int (*arg)(struct ldlm_lock *lock, void *req_cookie,
- ldlm_mode_t mode, int flags, void *data));
-void ldlm_unregister_intent(void);
-void ldlm_lock2handle(struct ldlm_lock *lock, struct lustre_handle *lockh);
-struct ldlm_lock *__ldlm_handle2lock(struct lustre_handle *, int strict,
- int flags);
-void ldlm_cancel_callback(struct ldlm_lock *);
-int ldlm_lock_set_data(struct lustre_handle *, void *data, int datalen);
-void ldlm_lock_remove_from_lru(struct ldlm_lock *);
-
-static inline struct ldlm_lock *ldlm_handle2lock(struct lustre_handle *h)
-{
- return __ldlm_handle2lock(h, 1, 0);
-}
-
-#define LDLM_LOCK_PUT(lock) \
-do { \
- /*LDLM_DEBUG(lock, "put");*/ \
- ldlm_lock_put(lock); \
-} while (0)
-
-#define LDLM_LOCK_GET(lock) \
-({ \
- ldlm_lock_get(lock); \
- /*LDLM_DEBUG(lock, "get");*/ \
- lock; \
-})
-
-struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock);
-void ldlm_lock_put(struct ldlm_lock *lock);
-void ldlm_lock_destroy(struct ldlm_lock *lock);
-void ldlm_lock2desc(struct ldlm_lock *lock, struct ldlm_lock_desc *desc);
-void ldlm_lock_addref(struct lustre_handle *lockh, __u32 mode);
-void ldlm_lock_addref_internal(struct ldlm_lock *, __u32 mode);
-void ldlm_lock_decref(struct lustre_handle *lockh, __u32 mode);
-void ldlm_grant_lock(struct ldlm_lock *lock);
-int ldlm_lock_match(struct ldlm_namespace *ns, __u64 *res_id, __u32 type,
- void *cookie, int cookielen, ldlm_mode_t mode,
- struct lustre_handle *lockh);
-struct ldlm_lock *
-ldlm_lock_create(struct ldlm_namespace *ns,
- struct lustre_handle *parent_lock_handle,
- __u64 *res_id, __u32 type, ldlm_mode_t mode, void *data,
- __u32 data_len);
-ldlm_error_t ldlm_lock_enqueue(struct ldlm_lock *lock, void *cookie,
- int cookie_len, int *flags,
- ldlm_completion_callback completion,
- ldlm_blocking_callback blocking);
-struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
- int *flags);
-void ldlm_lock_cancel(struct ldlm_lock *lock);
-void ldlm_cancel_locks_for_export(struct obd_export *export);
-void ldlm_run_ast_work(struct list_head *rpc_list);
-void ldlm_reprocess_all(struct ldlm_resource *res);
-void ldlm_lock_dump(struct ldlm_lock *lock);
-
-/* ldlm_test.c */
-int ldlm_test(struct obd_device *device, struct lustre_handle *connh);
-int ldlm_regression_start(struct obd_device *obddev,
- struct lustre_handle *connh,
- unsigned int threads, unsigned int max_locks_in,
- unsigned int num_resources_in,
- unsigned int num_extents_in);
-int ldlm_regression_stop(void);
-
-
-/* resource.c */
-struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 local);
-int ldlm_namespace_cleanup(struct ldlm_namespace *ns, int local_only);
-int ldlm_namespace_free(struct ldlm_namespace *ns);
-int ldlm_proc_setup(struct obd_device *obd);
-void ldlm_proc_cleanup(struct obd_device *obd);
-
-/* resource.c - internal */
-struct ldlm_resource *ldlm_resource_get(struct ldlm_namespace *ns,
- struct ldlm_resource *parent,
- __u64 *name, __u32 type, int create);
-struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res);
-int ldlm_resource_putref(struct ldlm_resource *res);
-void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
- struct ldlm_lock *lock);
-void ldlm_resource_unlink_lock(struct ldlm_lock *lock);
-void ldlm_res2desc(struct ldlm_resource *res, struct ldlm_resource_desc *desc);
-void ldlm_dump_all_namespaces(void);
-void ldlm_namespace_dump(struct ldlm_namespace *);
-void ldlm_resource_dump(struct ldlm_resource *);
-int ldlm_lock_change_resource(struct ldlm_lock *, __u64 new_resid[3]);
-
-/* ldlm_request.c */
-int ldlm_completion_ast(struct ldlm_lock *lock, int flags);
-int ldlm_cli_enqueue(struct lustre_handle *conn,
- struct ptlrpc_request *req,
- struct ldlm_namespace *ns,
- struct lustre_handle *parent_lock_handle,
- __u64 *res_id,
- __u32 type,
- void *cookie, int cookielen,
- ldlm_mode_t mode,
- int *flags,
- ldlm_completion_callback completion,
- ldlm_blocking_callback callback,
- void *data,
- __u32 data_len,
- struct lustre_handle *lockh);
-int ldlm_match_or_enqueue(struct lustre_handle *connh,
- struct ptlrpc_request *req,
- struct ldlm_namespace *ns,
- struct lustre_handle *parent_lock_handle,
- __u64 *res_id,
- __u32 type,
- void *cookie, int cookielen,
- ldlm_mode_t mode,
- int *flags,
- ldlm_completion_callback completion,
- ldlm_blocking_callback callback,
- void *data,
- __u32 data_len,
- struct lustre_handle *lockh);
-int ldlm_server_ast(struct lustre_handle *lockh, struct ldlm_lock_desc *new,
- void *data, __u32 data_len);
-int ldlm_cli_convert(struct lustre_handle *, int new_mode, int *flags);
-int ldlm_cli_cancel(struct lustre_handle *lockh);
-int ldlm_cli_cancel_unused(struct ldlm_namespace *, __u64 *, int flags);
-int ldlm_cancel_lru(struct ldlm_namespace *ns);
-
-/* mds/handler.c */
-/* This has to be here because recurisve inclusion sucks. */
-int mds_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
- void *data, __u32 data_len, int flag);
-
-#endif /* __KERNEL__ */
-
-/* ioctls for trying requests */
-#define IOC_LDLM_TYPE 'f'
-#define IOC_LDLM_MIN_NR 40
-
-#define IOC_LDLM_TEST _IOWR('f', 40, long)
-#define IOC_LDLM_DUMP _IOWR('f', 41, long)
-#define IOC_LDLM_REGRESS_START _IOWR('f', 42, long)
-#define IOC_LDLM_REGRESS_STOP _IOWR('f', 43, long)
-#define IOC_LDLM_MAX_NR 43
-
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-
-#ifndef __EXPORT_H
-#define __EXPORT_H
-
-#ifdef __KERNEL__
-
-#include <linux/lustre_idl.h>
-#include <linux/lustre_dlm.h>
-#include <linux/obd_filter.h>
-
-struct lov_export_data {
- struct list_head led_open_head;
-};
-
-struct obd_export {
- __u64 exp_cookie;
- struct list_head exp_obd_chain;
- struct list_head exp_conn_chain;
- struct obd_device *exp_obd;
- struct ptlrpc_connection *exp_connection;
- struct ldlm_export_data exp_ldlm_data;
- union {
- struct mds_export_data eu_mds_data;
- struct filter_export_data eu_filter_data;
- struct lov_export_data eu_lov_data;
- } u;
-};
-
-#define exp_mds_data u.eu_mds_data
-#define exp_lov_data u.eu_lov_data
-#define exp_filter_data u.eu_filter_data
-
-extern struct obd_export *class_conn2export(struct lustre_handle *conn);
-extern struct obd_device *class_conn2obd(struct lustre_handle *conn);
-#endif /* __KERNEL__ */
-
-#endif /* __EXPORT_H */
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-
-#ifndef _LUSTRE_HA_H
-#define _LUSTRE_HA_H
-
-#define LUSTRE_HA_NAME "ptlrpc"
-
-struct recovd_data;
-struct recovd_obd;
-struct obd_import;
-struct ptlrpc_connection;
-
-/* rd_phase/rd_next_phase values */
-#define RD_IDLE 0
-#define RD_TROUBLED 1
-#define RD_PREPARING 2
-#define RD_PREPARED 3
-#define RD_RECOVERING 4
-#define RD_RECOVERED 5
-#define RD_FAILED 6
-
-/* recovd_state values */
-#define RECOVD_READY 1
-#define RECOVD_STOPPING 2 /* how cleanup tells recovd to quit */
-#define RECOVD_STOPPED 4 /* after recovd has stopped */
-
-#define PTLRPC_RECOVD_PHASE_PREPARE 1
-#define PTLRPC_RECOVD_PHASE_RECOVER 2
-#define PTLRPC_RECOVD_PHASE_FAILURE 3
-
-typedef int (*ptlrpc_recovery_cb_t)(struct recovd_data *, int);
-
-struct recovd_data {
- /* you must hold recovd->recovd_lock when touching rd_managed_chain */
- struct list_head rd_managed_chain;
- ptlrpc_recovery_cb_t rd_recover;
- struct recovd_obd *rd_recovd;
- __u32 rd_phase;
- __u32 rd_next_phase;
- __u32 rd_flags;
-};
-
-void recovd_conn_fail(struct ptlrpc_connection *conn);
-void recovd_conn_manage(struct ptlrpc_connection *conn, struct recovd_obd *mgr,
- ptlrpc_recovery_cb_t recover);
-void recovd_conn_unmanage(struct ptlrpc_connection *conn);
-void recovd_conn_fixed(struct ptlrpc_connection *conn);
-int recovd_setup(struct recovd_obd *mgr);
-int recovd_cleanup(struct recovd_obd *mgr);
-
-extern struct recovd_obd *ptlrpc_recovd;
-
-int ptlrpc_run_recovery_upcall(struct ptlrpc_connection *conn);
-int ptlrpc_reconnect_import(struct obd_import *imp, int rq_opc);
-int ptlrpc_replay(struct obd_import *imp, int send_last_flag);
-int ptlrpc_resend(struct obd_import *imp);
-void ptlrpc_free_committed(struct obd_import *imp);
-void ptlrpc_wake_delayed(struct obd_import *imp);
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * (Un)packing of OST requests
- */
-
-#ifndef _LUSTRE_IDL_H_
-#define _LUSTRE_IDL_H_
-
-#ifdef __KERNEL__
-# include <linux/ioctl.h>
-# include <asm/types.h>
-# include <linux/types.h>
-# include <linux/list.h>
-#else
-# define __KERNEL__
-# include <asm/types.h>
-# include <linux/list.h>
-# undef __KERNEL__
-# include <stdint.h>
-#endif
-/*
- * this file contains all data structures used in Lustre interfaces:
- * - obdo and obd_request records
- * - mds_request records
- * - ldlm data
- * - ioctl's
- */
-
-/*
- * GENERAL STUFF
- */
-typedef __u8 obd_uuid_t[37];
-
-/* FOO_REQUEST_PORTAL is for incoming requests on the FOO
- * FOO_REPLY_PORTAL is for incoming replies on the FOO
- * FOO_BULK_PORTAL is for incoming bulk on the FOO
- */
-
-#define CONNMGR_REQUEST_PORTAL 1
-#define CONNMGR_REPLY_PORTAL 2
-#define OSC_REQUEST_PORTAL 3
-#define OSC_REPLY_PORTAL 4
-#define OSC_BULK_PORTAL 5
-#define OST_REQUEST_PORTAL 6
-#define OST_REPLY_PORTAL 7
-#define OST_BULK_PORTAL 8
-#define MDC_REQUEST_PORTAL 9
-#define MDC_REPLY_PORTAL 10
-#define MDC_BULK_PORTAL 11
-#define MDS_REQUEST_PORTAL 12
-#define MDS_REPLY_PORTAL 13
-#define MDS_BULK_PORTAL 14
-#define LDLM_CB_REQUEST_PORTAL 15
-#define LDLM_CB_REPLY_PORTAL 16
-#define LDLM_CANCEL_REQUEST_PORTAL 17
-#define LDLM_CANCEL_REPLY_PORTAL 18
-
-#define SVC_KILLED 1
-#define SVC_EVENT 2
-#define SVC_SIGNAL 4
-#define SVC_RUNNING 8
-#define SVC_STOPPING 16
-#define SVC_STOPPED 32
-
-#define LUSTRE_CONN_NEW 1
-#define LUSTRE_CONN_CON 2
-#define LUSTRE_CONN_RECOVD 3
-#define LUSTRE_CONN_FULL 4
-
-/* packet types */
-#define PTL_RPC_MSG_REQUEST 4711
-#define PTL_RPC_MSG_ERR 4712
-#define PTL_RPC_MSG_REPLY 4713
-
-#define PTLRPC_MSG_MAGIC (cpu_to_le32(0x0BD00BD0))
-#define PTLRPC_MSG_VERSION (cpu_to_le32(0x00040001))
-
-struct lustre_handle {
- __u64 addr;
- __u64 cookie;
-};
-#define DEAD_HANDLE_MAGIC 0xdeadbeefcafebabe
-
-static inline void ptlrpc_invalidate_handle(struct lustre_handle *hdl)
-{
- hdl->addr = hdl->cookie = 0; /* XXX invalid enough? */
-}
-
-/* we depend on this structure to be 8-byte aligned */
-struct lustre_msg {
- __u64 addr;
- __u64 cookie; /* security token */
- __u32 magic;
- __u32 type;
- __u32 version;
- __u32 opc;
- __u64 last_xid;
- __u64 last_committed;
- __u64 transno;
- __u32 status;
- __u32 bufcount;
- __u32 flags;
- __u32 buflens[0];
-};
-
-/* Flags that are operation-specific go in the top 16 bits. */
-#define MSG_OP_FLAG_MASK 0xffff0000
-#define MSG_OP_FLAG_SHIFT 16
-
-/* Flags that apply to all requests are in the bottom 16 bits */
-#define MSG_GEN_FLAG_MASK 0x0000ffff
-#define MSG_LAST_REPLAY 1
-
-static inline int lustre_msg_get_flags(struct lustre_msg *msg)
-{
- return (msg->flags & MSG_GEN_FLAG_MASK);
-}
-
-static inline void lustre_msg_set_flags(struct lustre_msg *msg, int flags)
-{
- msg->flags &= ~MSG_GEN_FLAG_MASK;
- msg->flags |= MSG_GEN_FLAG_MASK & flags;
-}
-
-static inline int lustre_msg_get_op_flags(struct lustre_msg *msg)
-{
- return (msg->flags >> MSG_OP_FLAG_SHIFT);
-}
-
-static inline void lustre_msg_set_op_flags(struct lustre_msg *msg, int flags)
-{
- msg->flags &= ~MSG_OP_FLAG_MASK;
- msg->flags |= ((flags & MSG_GEN_FLAG_MASK) << MSG_OP_FLAG_SHIFT);
-}
-
-#define CONNMGR_REPLY 0
-#define CONNMGR_CONNECT 1
-
-/*
- * OST requests: OBDO & OBD request records
- */
-
-/* opcodes */
-#define OST_REPLY 0 /* reply ? */
-#define OST_GETATTR 1
-#define OST_SETATTR 2
-#define OST_READ 3
-#define OST_WRITE 4
-#define OST_CREATE 5
-#define OST_DESTROY 6
-#define OST_GET_INFO 7
-#define OST_CONNECT 8
-#define OST_DISCONNECT 9
-#define OST_PUNCH 10
-#define OST_OPEN 11
-#define OST_CLOSE 12
-#define OST_STATFS 13
-
-
-typedef uint64_t obd_id;
-typedef uint64_t obd_gr;
-typedef uint64_t obd_time;
-typedef uint64_t obd_size;
-typedef uint64_t obd_off;
-typedef uint64_t obd_blocks;
-typedef uint32_t obd_blksize;
-typedef uint32_t obd_mode;
-typedef uint32_t obd_uid;
-typedef uint32_t obd_gid;
-typedef uint64_t obd_rdev;
-typedef uint32_t obd_flag;
-typedef uint32_t obd_count;
-
-#define OBD_FL_INLINEDATA (0x00000001)
-#define OBD_FL_OBDMDEXISTS (0x00000002)
-
-#define OBD_INLINESZ 60
-
-/* Note: 64-bit types are 64-bit aligned in structure */
-struct obdo {
- obd_id o_id;
- obd_gr o_gr;
- obd_time o_atime;
- obd_time o_mtime;
- obd_time o_ctime;
- obd_size o_size;
- obd_blocks o_blocks;
- obd_rdev o_rdev;
- obd_blksize o_blksize;
- obd_mode o_mode;
- obd_uid o_uid;
- obd_gid o_gid;
- obd_flag o_flags;
- obd_count o_nlink;
- obd_count o_generation;
- obd_flag o_valid; /* hot fields in this obdo */
- obd_flag o_obdflags;
- __u32 o_easize;
- char o_inline[OBD_INLINESZ];
-};
-
-struct lov_object_id { /* per-child structure */
- __u64 l_object_id;
-};
-
-#define LOV_MAGIC 0x0BD00BD0
-
-struct lov_mds_md {
- __u32 lmm_magic;
- __u32 lmm_unused; /* was packed size of extended attribute */
- __u64 lmm_object_id; /* lov object id */
- __u32 lmm_stripe_offset; /* starting stripe offset in lmd_objects */
- __u32 lmm_stripe_count; /* number of stipes in use for this object */
- __u64 lmm_stripe_size; /* size of the stripe */
- __u32 lmm_ost_count; /* how many OST idx are in this LOV md */
- __u32 lmm_stripe_pattern; /* per-lov object stripe pattern */
- struct lov_object_id lmm_objects[0];
-};
-
-#define OBD_MD_FLALL (0xffffffff)
-#define OBD_MD_FLID (0x00000001) /* object ID */
-#define OBD_MD_FLATIME (0x00000002) /* access time */
-#define OBD_MD_FLMTIME (0x00000004) /* data modification time */
-#define OBD_MD_FLCTIME (0x00000008) /* change time */
-#define OBD_MD_FLSIZE (0x00000010) /* size */
-#define OBD_MD_FLBLOCKS (0x00000020) /* allocated blocks count */
-#define OBD_MD_FLBLKSZ (0x00000040) /* block size */
-#define OBD_MD_FLMODE (0x00000080) /* access bits (mode & ~S_IFMT) */
-#define OBD_MD_FLTYPE (0x00000100) /* object type (mode & S_IFMT) */
-#define OBD_MD_FLUID (0x00000200) /* user ID */
-#define OBD_MD_FLGID (0x00000400) /* group ID */
-#define OBD_MD_FLFLAGS (0x00000800) /* flags word */
-#define OBD_MD_FLOBDFLG (0x00001000)
-#define OBD_MD_FLNLINK (0x00002000) /* link count */
-#define OBD_MD_FLGENER (0x00004000) /* generation number */
-#define OBD_MD_FLINLINE (0x00008000) /* inline data */
-#define OBD_MD_FLRDEV (0x00010000) /* device number */
-#define OBD_MD_FLEASIZE (0x00020000) /* extended attribute data */
-#define OBD_MD_LINKNAME (0x00040000) /* symbolic link target */
-#define OBD_MD_FLHANDLE (0x00080000) /* file handle */
-#define OBD_MD_FLNOTOBD (~(OBD_MD_FLOBDFLG | OBD_MD_FLBLOCKS | OBD_MD_LINKNAME|\
- OBD_MD_FLEASIZE | OBD_MD_FLHANDLE))
-
-struct obd_statfs {
- __u64 os_type;
- __u64 os_blocks;
- __u64 os_bfree;
- __u64 os_bavail;
- __u64 os_files;
- __u64 os_ffree;
- __u8 os_fsid[40];
- __u32 os_bsize;
- __u32 os_namelen;
- __u32 os_spare[12];
-};
-
-/* ost_body.data values for OST_BRW */
-
-#define OBD_BRW_READ 0x1
-#define OBD_BRW_WRITE 0x2
-#define OBD_BRW_RWMASK (OBD_BRW_READ | OBD_BRW_WRITE)
-#define OBD_BRW_CREATE 0x4
-
-#define OBD_OBJECT_EOF 0xffffffffffffffffULL
-
-struct obd_ioobj {
- obd_id ioo_id;
- obd_gr ioo_gr;
- /* struct lustre_handle ioo_handle; XXX in the future */
- __u32 ioo_type;
- __u32 ioo_bufcnt;
-};
-
-struct niobuf_remote {
- __u64 offset;
- __u32 len;
- __u32 xid;
- __u32 flags;
-};
-
-#define CONNMGR_REPLY 0
-#define CONNMGR_CONNECT 1
-
-struct connmgr_body {
- __u64 conn;
- __u64 conn_token;
- __u32 generation;
- obd_uuid_t conn_uuid;
-};
-
-/* request structure for OST's */
-
-#define OST_REQ_HAS_OA1 0x1
-
-struct ost_body {
- struct obdo oa;
-};
-
-/*
- * MDS REQ RECORDS
- */
-
-/* opcodes */
-#define MDS_GETATTR 1
-#define MDS_OPEN 2
-#define MDS_CLOSE 3
-#define MDS_REINT 4
-#define MDS_READPAGE 6
-#define MDS_CONNECT 7
-#define MDS_DISCONNECT 8
-#define MDS_GETSTATUS 9
-#define MDS_STATFS 10
-#define MDS_GETLOVINFO 11
-
-#define REINT_SETATTR 1
-#define REINT_CREATE 2
-#define REINT_LINK 3
-#define REINT_UNLINK 4
-#define REINT_RENAME 5
-#define REINT_MAX 5
-
-#define REINT_OPCODE_MASK 0xff /* opcodes must fit into this mask */
-#define REINT_REPLAYING 0x1000 /* masked into the opcode to indicate replay */
-
-struct ll_fid {
- __u64 id;
- __u32 generation;
- __u32 f_type;
-};
-
-
-#define MDS_STATUS_CONN 1
-#define MDS_STATUS_LOV 2
-
-struct mds_status_req {
- __u32 flags;
- __u32 repbuf;
-};
-
-struct mds_fileh_body {
- struct ll_fid f_fid;
- struct lustre_handle f_handle;
-};
-
-struct mds_conn_status {
- struct ll_fid rootfid;
- __u64 xid;
- __u64 last_committed;
- __u64 last_rcvd;
- /* XXX preallocated quota & obj fields here */
-};
-
-struct mds_body {
- struct ll_fid fid1;
- struct ll_fid fid2;
- struct lustre_handle handle;
- __u64 size;
- __u32 ino; /* make this a __u64 */
- __u32 valid;
- __u32 fsuid;
- __u32 fsgid;
- __u32 capability;
- __u32 mode;
- __u32 uid;
- __u32 gid;
- __u32 mtime;
- __u32 ctime;
- __u32 atime;
- __u32 flags;
- __u32 rdev;
- __u32 nlink;
- __u32 generation;
-};
-
-/* This is probably redundant with OBD_MD_FLEASIZE, but we need an audit */
-#define MDS_OPEN_HAS_EA 1 /* this open has an EA, for a delayed create*/
-
-/* MDS update records */
-
-
-//struct mds_update_record_hdr {
-// __u32 ur_opcode;
-//};
-
-struct mds_rec_setattr {
- __u32 sa_opcode;
- __u32 sa_fsuid;
- __u32 sa_fsgid;
- __u32 sa_cap;
- __u32 sa_reserved;
- __u32 sa_valid;
- struct ll_fid sa_fid;
- __u32 sa_mode;
- __u32 sa_uid;
- __u32 sa_gid;
- __u32 sa_attr_flags;
- __u64 sa_size;
- __u64 sa_atime;
- __u64 sa_mtime;
- __u64 sa_ctime;
-};
-
-struct mds_rec_create {
- __u32 cr_opcode;
- __u32 cr_fsuid;
- __u32 cr_fsgid;
- __u32 cr_cap;
- __u32 cr_reserved;
- __u32 cr_mode;
- struct ll_fid cr_fid;
- struct ll_fid cr_replayfid;
- __u32 cr_uid;
- __u32 cr_gid;
- __u64 cr_time;
- __u64 cr_rdev;
-};
-
-struct mds_rec_link {
- __u32 lk_opcode;
- __u32 lk_fsuid;
- __u32 lk_fsgid;
- __u32 lk_cap;
- struct ll_fid lk_fid1;
- struct ll_fid lk_fid2;
-};
-
-struct mds_rec_unlink {
- __u32 ul_opcode;
- __u32 ul_fsuid;
- __u32 ul_fsgid;
- __u32 ul_cap;
- __u32 ul_reserved;
- __u32 ul_mode;
- struct ll_fid ul_fid1;
- struct ll_fid ul_fid2;
-};
-
-struct mds_rec_rename {
- __u32 rn_opcode;
- __u32 rn_fsuid;
- __u32 rn_fsgid;
- __u32 rn_cap;
- struct ll_fid rn_fid1;
- struct ll_fid rn_fid2;
-};
-
-
-/*
- * LOV data structures
- */
-
-#define LOV_RAID0 0
-#define LOV_RAIDRR 1
-
-struct lov_desc {
- __u32 ld_tgt_count; /* how many OBD's */
- __u32 ld_active_tgt_count; /* how many active */
- __u32 ld_default_stripe_count; /* how many objects are used */
- __u64 ld_default_stripe_size; /* in bytes */
- __u64 ld_default_stripe_offset; /* in bytes */
- __u32 ld_pattern; /* RAID 0,1 etc */
- obd_uuid_t ld_uuid;
-};
-
-/*
- * LDLM requests:
- */
-/* opcodes -- MUST be distinct from OST/MDS opcodes */
-#define LDLM_ENQUEUE 101
-#define LDLM_CONVERT 102
-#define LDLM_CANCEL 103
-#define LDLM_BL_CALLBACK 104
-#define LDLM_CP_CALLBACK 105
-
-#define RES_NAME_SIZE 3
-#define RES_VERSION_SIZE 4
-
-/* lock types */
-typedef enum {
- LCK_EX = 1,
- LCK_PW,
- LCK_PR,
- LCK_CW,
- LCK_CR,
- LCK_NL
-} ldlm_mode_t;
-
-struct ldlm_extent {
- __u64 start;
- __u64 end;
-};
-
-struct ldlm_intent {
- __u64 opc;
-};
-
-/* Note this unaligned structure; as long as it's only used in ldlm_request
- * below, we're probably fine. */
-struct ldlm_resource_desc {
- __u32 lr_type;
- __u64 lr_name[RES_NAME_SIZE];
- __u32 lr_version[RES_VERSION_SIZE];
-};
-
-struct ldlm_lock_desc {
- struct ldlm_resource_desc l_resource;
- ldlm_mode_t l_req_mode;
- ldlm_mode_t l_granted_mode;
- struct ldlm_extent l_extent;
- __u32 l_version[RES_VERSION_SIZE];
-};
-
-struct ldlm_request {
- __u32 lock_flags;
- struct ldlm_lock_desc lock_desc;
- struct lustre_handle lock_handle1;
- struct lustre_handle lock_handle2;
-};
-
-struct ldlm_reply {
- __u32 lock_flags;
- __u32 lock_mode;
- __u64 lock_resource_name[RES_NAME_SIZE];
- struct lustre_handle lock_handle;
- struct ldlm_extent lock_extent; /* XXX make this policy 1 &2 */
- __u64 lock_policy_res1;
- __u64 lock_policy_res2;
-};
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-
-#ifndef __IMPORT_H
-#define __IMPORT_H
-
-#ifdef __KERNEL__
-
-#define IMP_INVALID 1
-#define IMP_REPLAYABLE 2
-
-typedef int (*import_recover_t)(struct obd_import *imp, int phase);
-
-#include <linux/lustre_idl.h>
-struct obd_import {
- import_recover_t imp_recover;
- struct ptlrpc_connection *imp_connection;
- struct ptlrpc_client *imp_client;
- struct lustre_handle imp_handle;
- struct list_head imp_chain;
-
- /* Lists of requests that are retained for replay, waiting for a reply,
- * or waiting for recovery to complete, respectively.
- */
- struct list_head imp_replay_list;
- struct list_head imp_sending_list;
- struct list_head imp_delayed_list;
-
- struct obd_device *imp_obd;
- int imp_flags;
- int imp_level;
- __u64 imp_last_xid;
- __u64 imp_max_transno;
- __u64 imp_peer_last_xid;
- __u64 imp_peer_committed_transno;
-
- /* Protects flags, level, *_xid, *_list */
- spinlock_t imp_lock;
-};
-
-extern struct obd_import *class_conn2cliimp(struct lustre_handle *);
-extern struct obd_import *class_conn2ldlmimp(struct lustre_handle *);
-
-#endif /* __KERNEL__ */
-
-#endif /* __IMPORT_H */
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Basic Lustre library routines.
- *
- */
-
-#ifndef _LUSTRE_LIB_H
-#define _LUSTRE_LIB_H
-
-#ifndef __KERNEL__
-# include <string.h>
-#else
-# include <asm/semaphore.h>
-#endif
-#include <linux/kp30.h> /* XXX just for LASSERT! */
-#include <linux/portals_lib.h>
-#include <linux/lustre_idl.h>
-
-#ifdef __KERNEL__
-/* l_net.c */
-struct ptlrpc_request;
-struct obd_device;
-struct recovd_data;
-struct recovd_obd;
-#include <linux/lustre_ha.h>
-
-int target_handle_connect(struct ptlrpc_request *req);
-int target_handle_disconnect(struct ptlrpc_request *req);
-int client_obd_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover);
-int client_obd_disconnect(struct lustre_handle *conn);
-int client_obd_setup(struct obd_device *obddev, obd_count len, void *buf);
-int client_obd_cleanup(struct obd_device * obddev);
-struct client_obd *client_conn2cli(struct lustre_handle *conn);
-
-int target_revoke_connection(struct recovd_data *rd, int phase);
-
-/* l_lock.c */
-struct lustre_lock {
- int l_depth;
- struct task_struct *l_owner;
- struct semaphore l_sem;
- spinlock_t l_spin;
-};
-
-void l_lock_init(struct lustre_lock *);
-void l_lock(struct lustre_lock *);
-void l_unlock(struct lustre_lock *);
-int l_has_lock(struct lustre_lock *);
-
-#define CB_PHASE_START 12
-#define CB_PHASE_FINISH 13
-
-/* This list head doesn't need to be locked, because it's only manipulated by
- * one thread at a time. */
-struct obd_brw_set {
- struct list_head brw_desc_head; /* list of ptlrpc_bulk_desc */
- wait_queue_head_t brw_waitq;
- atomic_t brw_refcount;
- int brw_flags;
-
- int (*brw_callback)(struct obd_brw_set *, int phase);
-};
-
-/* simple.c */
-struct obd_run_ctxt;
-struct obd_ucred;
-void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *cred);
-void pop_ctxt(struct obd_run_ctxt *saved, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *cred);
-struct dentry *simple_mkdir(struct dentry *dir, char *name, int mode);
-struct dentry *simple_mknod(struct dentry *dir, char *name, int mode);
-int lustre_fread(struct file *file, char *str, int len, loff_t *off);
-int lustre_fwrite(struct file *file, const char *str, int len, loff_t *off);
-int lustre_fsync(struct file *file);
-
-static inline void l_dput(struct dentry *de)
-{
- if (!de || IS_ERR(de))
- return;
- shrink_dcache_parent(de);
- LASSERT(atomic_read(&de->d_count) > 0);
- dput(de);
-}
-
-static inline void ll_sleep(int t)
-{
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(t * HZ);
- set_current_state(TASK_RUNNING);
-}
-#endif
-
-/* FIXME: This needs to validate pointers and cookies */
-static inline void *lustre_handle2object(struct lustre_handle *handle)
-{
- if (handle)
- return (void *)(unsigned long)(handle->addr);
- return NULL;
-}
-
-static inline void ldlm_object2handle(void *object, struct lustre_handle *handle)
-{
- handle->addr = (__u64)(unsigned long)object;
-}
-
-struct obd_statfs;
-struct statfs;
-void statfs_pack(struct obd_statfs *osfs, struct statfs *sfs);
-void statfs_unpack(struct statfs *sfs, struct obd_statfs *osfs);
-void obd_statfs_pack(struct obd_statfs *tgt, struct obd_statfs *src);
-static inline void
-obd_statfs_unpack(struct obd_statfs *tgt, struct obd_statfs *src)
-{
- obd_statfs_pack(tgt, src);
-}
-
-#include <linux/portals_lib.h>
-
-/*
- * OBD IOCTLS
- */
-#define OBD_IOCTL_VERSION 0x00010001
-
-struct obd_ioctl_data {
- uint32_t ioc_len;
- uint32_t ioc_version;
-
- uint64_t ioc_addr;
- uint64_t ioc_cookie;
- uint32_t ioc_conn1;
- uint32_t ioc_conn2;
-
- struct obdo ioc_obdo1;
- struct obdo ioc_obdo2;
-
- obd_size ioc_count;
- obd_off ioc_offset;
- uint32_t ioc_dev;
- uint32_t ____padding;
-
- /* buffers the kernel will treat as user pointers */
- uint32_t ioc_plen1;
- char *ioc_pbuf1;
- uint32_t ioc_plen2;
- char *ioc_pbuf2;
-
- /* two inline buffers */
- uint32_t ioc_inllen1;
- char *ioc_inlbuf1;
- uint32_t ioc_inllen2;
- char *ioc_inlbuf2;
- uint32_t ioc_inllen3;
- char *ioc_inlbuf3;
-
- char ioc_bulk[0];
-};
-
-struct obd_ioctl_hdr {
- uint32_t ioc_len;
- uint32_t ioc_version;
-};
-
-static inline int obd_ioctl_packlen(struct obd_ioctl_data *data)
-{
- int len = size_round(sizeof(struct obd_ioctl_data));
- len += size_round(data->ioc_inllen1);
- len += size_round(data->ioc_inllen2);
- len += size_round(data->ioc_inllen3);
- return len;
-}
-
-
-static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
-{
- if (data->ioc_len > (1<<30)) {
- printk("OBD ioctl: ioc_len larger than 1<<30\n");
- return 1;
- }
- if (data->ioc_inllen1 > (1<<30)) {
- printk("OBD ioctl: ioc_inllen1 larger than 1<<30\n");
- return 1;
- }
- if (data->ioc_inllen2 > (1<<30)) {
- printk("OBD ioctl: ioc_inllen2 larger than 1<<30\n");
- return 1;
- }
-
- if (data->ioc_inllen3 > (1<<30)) {
- printk("OBD ioctl: ioc_inllen3 larger than 1<<30\n");
- return 1;
- }
- if (data->ioc_inlbuf1 && !data->ioc_inllen1) {
- printk("OBD ioctl: inlbuf1 pointer but 0 length\n");
- return 1;
- }
- if (data->ioc_inlbuf2 && !data->ioc_inllen2) {
- printk("OBD ioctl: inlbuf2 pointer but 0 length\n");
- return 1;
- }
- if (data->ioc_inlbuf3 && !data->ioc_inllen3) {
- printk("OBD ioctl: inlbuf3 pointer but 0 length\n");
- return 1;
- }
- if (data->ioc_pbuf1 && !data->ioc_plen1) {
- printk("OBD ioctl: pbuf1 pointer but 0 length\n");
- return 1;
- }
- if (data->ioc_pbuf2 && !data->ioc_plen2) {
- printk("OBD ioctl: pbuf2 pointer but 0 length\n");
- return 1;
- }
- /*
- if (data->ioc_inllen1 && !data->ioc_inlbuf1) {
- printk("OBD ioctl: inllen1 set but NULL pointer\n");
- return 1;
- }
- if (data->ioc_inllen2 && !data->ioc_inlbuf2) {
- printk("OBD ioctl: inllen2 set but NULL pointer\n");
- return 1;
- }
- if (data->ioc_inllen3 && !data->ioc_inlbuf3) {
- printk("OBD ioctl: inllen3 set but NULL pointer\n");
- return 1;
- }
- */
- if (data->ioc_plen1 && !data->ioc_pbuf1) {
- printk("OBD ioctl: plen1 set but NULL pointer\n");
- return 1;
- }
- if (data->ioc_plen2 && !data->ioc_pbuf2) {
- printk("OBD ioctl: plen2 set but NULL pointer\n");
- return 1;
- }
- if (obd_ioctl_packlen(data) != data->ioc_len ) {
- printk("OBD ioctl: packlen exceeds ioc_len\n");
- return 1;
- }
-#if 0
- if (data->ioc_inllen1 &&
- data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') {
- printk("OBD ioctl: inlbuf1 not 0 terminated\n");
- return 1;
- }
- if (data->ioc_inllen2 &&
- data->ioc_bulk[size_round(data->ioc_inllen1) + data->ioc_inllen2 - 1] != '\0') {
- printk("OBD ioctl: inlbuf2 not 0 terminated\n");
- return 1;
- }
- if (data->ioc_inllen3 &&
- data->ioc_bulk[size_round(data->ioc_inllen1) + size_round(data->ioc_inllen2)
- + data->ioc_inllen3 - 1] != '\0') {
- printk("OBD ioctl: inlbuf3 not 0 terminated\n");
- return 1;
- }
-#endif
- return 0;
-}
-
-#ifndef __KERNEL__
-static inline int obd_ioctl_pack(struct obd_ioctl_data *data, char **pbuf,
- int max)
-{
- char *ptr;
- struct obd_ioctl_data *overlay;
- data->ioc_len = obd_ioctl_packlen(data);
- data->ioc_version = OBD_IOCTL_VERSION;
-
- if (*pbuf && data->ioc_len > max)
- return 1;
- if (*pbuf == NULL) {
- *pbuf = malloc(data->ioc_len);
- }
- if (!*pbuf)
- return 1;
- overlay = (struct obd_ioctl_data *)*pbuf;
- memcpy(*pbuf, data, sizeof(*data));
-
- ptr = overlay->ioc_bulk;
- if (data->ioc_inlbuf1)
- LOGL(data->ioc_inlbuf1, data->ioc_inllen1, ptr);
- if (data->ioc_inlbuf2)
- LOGL(data->ioc_inlbuf2, data->ioc_inllen2, ptr);
- if (data->ioc_inlbuf3)
- LOGL(data->ioc_inlbuf3, data->ioc_inllen3, ptr);
- if (obd_ioctl_is_invalid(overlay))
- return 1;
-
- return 0;
-}
-
-static inline int obd_ioctl_unpack(struct obd_ioctl_data *data, char *pbuf,
- int max)
-{
- char *ptr;
- struct obd_ioctl_data *overlay;
-
- if (!pbuf)
- return 1;
- overlay = (struct obd_ioctl_data *)pbuf;
-
- /* Preserve the caller's buffer pointers */
- overlay->ioc_inlbuf1 = data->ioc_inlbuf1;
- overlay->ioc_inlbuf2 = data->ioc_inlbuf2;
- overlay->ioc_inlbuf3 = data->ioc_inlbuf3;
-
- memcpy(data, pbuf, sizeof(*data));
-
- ptr = overlay->ioc_bulk;
- if (data->ioc_inlbuf1)
- LOGU(data->ioc_inlbuf1, data->ioc_inllen1, ptr);
- if (data->ioc_inlbuf2)
- LOGU(data->ioc_inlbuf2, data->ioc_inllen2, ptr);
- if (data->ioc_inlbuf3)
- LOGU(data->ioc_inlbuf3, data->ioc_inllen3, ptr);
-
- return 0;
-}
-#else
-
-#include <linux/obd_support.h>
-
-/* buffer MUST be at least the size of obd_ioctl_hdr */
-static inline int obd_ioctl_getdata(char **buf, int *len, void *arg)
-{
- struct obd_ioctl_hdr hdr;
- struct obd_ioctl_data *data;
- int err;
- ENTRY;
-
- err = copy_from_user(&hdr, (void *)arg, sizeof(hdr));
- if ( err ) {
- EXIT;
- return err;
- }
-
- if (hdr.ioc_version != OBD_IOCTL_VERSION) {
- printk("OBD: version mismatch kernel vs application\n");
- return -EINVAL;
- }
-
- if (hdr.ioc_len > 8192) {
- printk("OBD: user buffer exceeds 8192 max buffer\n");
- return -EINVAL;
- }
-
- if (hdr.ioc_len < sizeof(struct obd_ioctl_data)) {
- printk("OBD: user buffer too small for ioctl\n");
- return -EINVAL;
- }
-
- OBD_ALLOC(*buf, hdr.ioc_len);
- if (!*buf) {
- CERROR("Cannot allocate control buffer of len %d\n",
- hdr.ioc_len);
- RETURN(-EINVAL);
- }
- *len = hdr.ioc_len;
- data = (struct obd_ioctl_data *)*buf;
-
- err = copy_from_user(*buf, (void *)arg, hdr.ioc_len);
- if ( err ) {
- EXIT;
- return err;
- }
-
- if (obd_ioctl_is_invalid(data)) {
- printk("OBD: ioctl not correctly formatted\n");
- return -EINVAL;
- }
-
- if (data->ioc_inllen1) {
- data->ioc_inlbuf1 = &data->ioc_bulk[0];
- }
-
- if (data->ioc_inllen2) {
- data->ioc_inlbuf2 = &data->ioc_bulk[0] + size_round(data->ioc_inllen1);
- }
-
- if (data->ioc_inllen3) {
- data->ioc_inlbuf3 = &data->ioc_bulk[0] + size_round(data->ioc_inllen1) +
- size_round(data->ioc_inllen2);
- }
-
- EXIT;
- return 0;
-}
-#endif
-
-#define OBD_IOC_CREATE _IOR ('f', 101, long)
-#define OBD_IOC_SETUP _IOW ('f', 102, long)
-#define OBD_IOC_CLEANUP _IO ('f', 103 )
-#define OBD_IOC_DESTROY _IOW ('f', 104, long)
-#define OBD_IOC_PREALLOCATE _IOWR('f', 105, long)
-#define OBD_IOC_DEC_USE_COUNT _IO ('f', 106 )
-#define OBD_IOC_SETATTR _IOW ('f', 107, long)
-#define OBD_IOC_GETATTR _IOR ('f', 108, long)
-#define OBD_IOC_READ _IOWR('f', 109, long)
-#define OBD_IOC_WRITE _IOWR('f', 110, long)
-#define OBD_IOC_CONNECT _IOR ('f', 111, long)
-#define OBD_IOC_DISCONNECT _IOW ('f', 112, long)
-#define OBD_IOC_STATFS _IOWR('f', 113, long)
-#define OBD_IOC_SYNC _IOR ('f', 114, long)
-#define OBD_IOC_READ2 _IOWR('f', 115, long)
-#define OBD_IOC_FORMAT _IOWR('f', 116, long)
-#define OBD_IOC_PARTITION _IOWR('f', 117, long)
-#define OBD_IOC_ATTACH _IOWR('f', 118, long)
-#define OBD_IOC_DETACH _IOWR('f', 119, long)
-#define OBD_IOC_COPY _IOWR('f', 120, long)
-#define OBD_IOC_MIGR _IOWR('f', 121, long)
-#define OBD_IOC_PUNCH _IOWR('f', 122, long)
-#define OBD_IOC_DEVICE _IOWR('f', 123, long)
-#define OBD_IOC_MODULE_DEBUG _IOWR('f', 124, long)
-#define OBD_IOC_BRW_READ _IOWR('f', 125, long)
-#define OBD_IOC_BRW_WRITE _IOWR('f', 126, long)
-#define OBD_IOC_NAME2DEV _IOWR('f', 127, long)
-#define OBD_IOC_NEWDEV _IOWR('f', 128, long)
-#define OBD_IOC_LIST _IOWR('f', 129, long)
-#define OBD_IOC_UUID2DEV _IOWR('f', 130, long)
-
-#define OBD_IOC_RECOVD_NEWCONN _IOWR('f', 131, long)
-#define OBD_IOC_LOV_SET_CONFIG _IOWR('f', 132, long)
-#define OBD_IOC_LOV_GET_CONFIG _IOWR('f', 133, long)
-#define OBD_IOC_LOV_CONFIG OBD_IOC_LOV_SET_CONFIG
-
-#define OBD_IOC_OPEN _IOWR('f', 134, long)
-#define OBD_IOC_CLOSE _IOWR('f', 135, long)
-
-#define OBD_IOC_RECOVD_FAILCONN _IOWR('f', 136, long)
-
-#define OBD_IOC_DEC_FS_USE_COUNT _IO ('f', 139 )
-
-#define OBD_GET_VERSION _IOWR ('f', 144, long)
-
-/*
- * l_wait_event is a flexible sleeping function, permitting simple caller
- * configuration of interrupt and timeout sensitivity along with actions to
- * be performed in the event of either exception.
- *
- * Common usage looks like this:
- *
- * struct l_wait_info lwi = LWI_TIMEOUT_INTR(timeout, timeout_handler,
- * intr_handler, callback_data);
- * rc = l_wait_event(waitq, condition, &lwi);
- *
- * (LWI_TIMEOUT and LWI_INTR macros are available for timeout- and
- * interrupt-only variants, respectively.)
- *
- * If a timeout is specified, the timeout_handler will be invoked in the event
- * that the timeout expires before the process is awakened. (Note that any
- * waking of the process will restart the timeout, even if the condition is
- * not satisfied and the process immediately returns to sleep. This might be
- * considered a bug.) If the timeout_handler returns non-zero, l_wait_event
- * will return -ETIMEDOUT and the caller will continue. If the handler returns
- * zero instead, the process will go back to sleep until it is awakened by the
- * waitq or some similar mechanism, or an interrupt occurs (if the caller has
- * asked for interrupts to be detected). The timeout will only fire once, so
- * callers should take care that a timeout_handler which returns zero will take
- * future steps to awaken the process. N.B. that these steps must include
- * making the provided condition become true.
- *
- * If the interrupt flag (lwi_signals) is non-zero, then the process will be
- * interruptible, and will be awakened by any "killable" signal (SIGTERM,
- * SIGKILL or SIGINT). If a timeout is also specified, then the process will
- * only become interruptible _after_ the timeout has expired, though it can be
- * awakened by a signal that was delivered before the timeout and is still
- * pending when the timeout expires. If a timeout is not specified, the process
- * will be interruptible at all times during l_wait_event.
- */
-
-struct l_wait_info {
- long lwi_timeout;
- int (*lwi_on_timeout)(void *);
- long lwi_signals;
- int (*lwi_on_signal)(void *); /* XXX return is ignored for now */
- void *lwi_cb_data;
-};
-
-#define LWI_TIMEOUT(time, cb, data) \
-((struct l_wait_info) { \
- lwi_timeout: time, \
- lwi_on_timeout: cb, \
- lwi_cb_data: data \
-})
-
-#define LWI_INTR(cb, data) \
-((struct l_wait_info) { \
- lwi_signals: 1, \
- lwi_on_signal: cb, \
- lwi_cb_data: data \
-})
-
-#define LWI_TIMEOUT_INTR(time, time_cb, sig_cb, data) \
-((struct l_wait_info) { \
- lwi_timeout: time, \
- lwi_on_timeout: time_cb, \
- lwi_signals: 1, \
- lwi_on_signal: sig_cb, \
- lwi_cb_data: data \
-})
-
-/* XXX this should be one mask-check */
-#define l_killable_pending(task) \
-(sigismember(&(task->pending.signal), SIGKILL) || \
- sigismember(&(task->pending.signal), SIGINT) || \
- sigismember(&(task->pending.signal), SIGTERM))
-
-#define __l_wait_event(wq, condition, info, ret) \
-do { \
- wait_queue_t __wait; \
- long __state; \
- int __timed_out = 0; \
- init_waitqueue_entry(&__wait, current); \
- \
- add_wait_queue(&wq, &__wait); \
- if (info->lwi_signals && !info->lwi_timeout) \
- __state = TASK_INTERRUPTIBLE; \
- else \
- __state = TASK_UNINTERRUPTIBLE; \
- for (;;) { \
- set_current_state(__state); \
- if (condition) \
- break; \
- if (__state == TASK_INTERRUPTIBLE && l_killable_pending(current)) {\
- if (info->lwi_on_signal) \
- info->lwi_on_signal(info->lwi_cb_data); \
- ret = -EINTR; \
- break; \
- } \
- if (info->lwi_timeout && !__timed_out) { \
- if (schedule_timeout(info->lwi_timeout) == 0) { \
- __timed_out = 1; \
- if (!info->lwi_on_timeout || \
- info->lwi_on_timeout(info->lwi_cb_data)) { \
- ret = -ETIMEDOUT; \
- break; \
- } \
- /* We'll take signals after a timeout. */ \
- if (info->lwi_signals) { \
- __state = TASK_INTERRUPTIBLE; \
- /* Check for a pending interrupt. */ \
- if (info->lwi_signals && l_killable_pending(current)) {\
- if (info->lwi_on_signal) \
- info->lwi_on_signal(info->lwi_cb_data); \
- ret = -EINTR; \
- break; \
- } \
- } \
- } \
- } else { \
- schedule(); \
- } \
- } \
- current->state = TASK_RUNNING; \
- remove_wait_queue(&wq, &__wait); \
-} while(0)
-
-#define l_wait_event(wq, condition, info) \
-({ \
- int __ret = 0; \
- struct l_wait_info *__info = (info); \
- if (!(condition)) \
- __l_wait_event(wq, condition, __info, __ret); \
- __ret; \
-})
-
-#endif /* _LUSTRE_LIB_H */
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * lustre lite cluster file system
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copyright (C) 2002 Cluster File Systems, Inc. <info@clusterfs.com>
- */
-
-
-
-#ifndef _LL_H
-#define _LL_H
-
-#ifdef __KERNEL__
-
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/proc_fs.h>
-
-#include <linux/obd_class.h>
-#include <linux/lustre_net.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_ha.h>
-
-extern kmem_cache_t *ll_file_data_slab;
-struct ll_file_data {
- struct lustre_handle fd_mdshandle;
- struct lustre_handle fd_osthandle;
- struct ptlrpc_request *fd_req;
- __u32 fd_flags;
-};
-
-struct lustre_intent_data {
- __u64 it_lock_handle[2];
- __u32 it_disposition;
- __u32 it_status;
- __u32 it_lock_mode;
-};
-
-struct ll_dentry_data {
- struct semaphore lld_it_sem;
-};
-
-#define ll_d2d(dentry) ((struct ll_dentry_data*) dentry->d_fsdata)
-
-struct ll_read_inode2_cookie {
- struct mds_body *lic_body;
- struct lov_mds_md *lic_lmm;
-};
-
-#define LL_INLINESZ 60
-struct ll_inode_info {
- struct lov_stripe_md *lli_smd;
- char *lli_symlink_name;
- struct semaphore lli_open_sem;
- atomic_t lli_open_count; /* see ll_file_release */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
- struct inode lli_vfs_inode;
-#endif
-};
-
-
-
-#define LL_SUPER_MAGIC 0x0BD00BD0
-
-#define LL_COMMITCBD_STOPPING 0x1
-#define LL_COMMITCBD_STOPPED 0x2
-#define LL_COMMITCBD_RUNNING 0x4
-
-#define LL_SBI_NOLCK 0x1
-
-struct ll_sb_info {
- obd_uuid_t ll_sb_uuid;
- struct lustre_handle ll_mdc_conn;
- struct lustre_handle ll_osc_conn;
- struct proc_dir_entry* ll_proc_root;
- obd_id ll_rootino; /* number of root inode */
-
- int ll_flags;
- wait_queue_head_t ll_commitcbd_waitq;
- wait_queue_head_t ll_commitcbd_ctl_waitq;
- int ll_commitcbd_flags;
- struct task_struct *ll_commitcbd_thread;
- time_t ll_commitcbd_waketime;
- time_t ll_commitcbd_timeout;
- spinlock_t ll_commitcbd_lock;
- struct list_head ll_conn_chain; /* per-conn chain of SBs */
-
- struct list_head ll_orphan_dentry_list; /*please don't ask -p*/
-};
-
-static inline struct ll_sb_info *ll_s2sbi(struct super_block *sb)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
- return (struct ll_sb_info *)(sb->s_fs_info);
-#else
- return (struct ll_sb_info *)(sb->u.generic_sbp);
-#endif
-}
-
-static inline struct lustre_handle *ll_s2obdconn(struct super_block *sb)
-{
- return &(ll_s2sbi(sb))->ll_osc_conn;
-}
-
-static inline struct client_obd *sbi2mdc(struct ll_sb_info *sbi)
-{
- struct obd_device *obd = class_conn2obd(&sbi->ll_mdc_conn);
- if (obd == NULL)
- LBUG();
- return &obd->u.cli;
-}
-
-// FIXME: replace the name of this with LL_SB to conform to kernel stuff
-static inline struct ll_sb_info *ll_i2sbi(struct inode *inode)
-{
- return ll_s2sbi(inode->i_sb);
-}
-
-
-// FIXME: replace the name of this with LL_I to conform to kernel stuff
-// static inline struct ll_inode_info *LL_I(struct inode *inode)
-static inline struct ll_inode_info *ll_i2info(struct inode *inode)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
- return container_of(inode, struct ll_inode_info, lli_vfs_inode);
-#else
- return (struct ll_inode_info *)&(inode->u.generic_ip);
-#endif
-}
-
-static inline struct lustre_handle *ll_i2obdconn(struct inode *inode)
-{
- return ll_s2obdconn(inode->i_sb);
-}
-
-static inline void ll_ino2fid(struct ll_fid *fid, obd_id ino, __u32 generation,
- int type)
-{
- fid->id = ino;
- fid->generation = generation;
- fid->f_type = type;
-}
-
-static inline void ll_inode2fid(struct ll_fid *fid, struct inode *inode)
-{
- ll_ino2fid(fid, inode->i_ino, inode->i_generation,
- inode->i_mode & S_IFMT);
-}
-
-static inline int ll_mds_max_easize(struct super_block *sb)
-{
- return sbi2mdc(ll_s2sbi(sb))->cl_max_mds_easize;
-}
-
-/* namei.c */
-int ll_lock(struct inode *dir, struct dentry *dentry,
- struct lookup_intent *it, struct lustre_handle *lockh);
-int ll_unlock(__u32 mode, struct lustre_handle *lockh);
-
-typedef int (*intent_finish_cb)(int flag, struct ptlrpc_request *,
- struct dentry **, struct lookup_intent *,
- int offset, obd_id ino);
-int ll_intent_lock(struct inode *parent, struct dentry **,
- struct lookup_intent *, intent_finish_cb);
-
-/* dcache.c */
-void ll_intent_release(struct dentry *, struct lookup_intent *);
-int ll_set_dd(struct dentry *de);
-
-/****
-
-I originally implmented these as functions, then realized a macro
-would be more helpful for debugging, so the CDEBUG messages show
-the current calling function. The orignal functions are in llite/dcache.c
-
-int ll_save_intent(struct dentry * de, struct lookup_intent * it);
-struct lookup_intent * ll_get_intent(struct dentry * de);
-****/
-
-#define IT_RELEASED_MAGIC 0xDEADCAFE
-
-#define LL_SAVE_INTENT(de, it) \
-do { \
- LASSERT(ll_d2d(de) != NULL); \
- \
- down(&ll_d2d(de)->lld_it_sem); \
- LASSERT(de->d_it == NULL); \
- de->d_it = it; \
- CDEBUG(D_DENTRY, "D_IT DOWN dentry %p fsdata %p intent: %s sem %d\n", \
- de, ll_d2d(de), ldlm_it2str(de->d_it->it_op), \
- atomic_read(&(ll_d2d(de)->lld_it_sem.count))); \
-} while(0)
-
-#define LL_GET_INTENT(de, it) \
-do { \
- it = de->d_it; \
- \
- LASSERT(ll_d2d(de) != NULL); \
- LASSERT(it); \
- LASSERT(it->it_op != IT_RELEASED_MAGIC); \
- \
- CDEBUG(D_DENTRY, "D_IT UP dentry %p fsdata %p intent: %s\n", \
- de, ll_d2d(de), ldlm_it2str(de->d_it->it_op)); \
- de->d_it = NULL; \
- it->it_op = IT_RELEASED_MAGIC; \
- up(&ll_d2d(de)->lld_it_sem); \
-} while(0)
-
-
-/* dir.c */
-extern struct file_operations ll_dir_operations;
-extern struct inode_operations ll_dir_inode_operations;
-
-/* file.c */
-extern struct file_operations ll_file_operations;
-extern struct inode_operations ll_file_inode_operations;
-struct ldlm_lock;
-int ll_lock_callback(struct ldlm_lock *, struct ldlm_lock_desc *, void *data,
- __u32 data_len, int flag);
-int ll_size_lock(struct inode *, struct lov_stripe_md *, obd_off start,
- int mode, struct lustre_handle **);
-int ll_size_unlock(struct inode *, struct lov_stripe_md *, int mode,
- struct lustre_handle *);
-int ll_file_size(struct inode *inode, struct lov_stripe_md *md);
-int ll_create_objects(struct super_block *sb, obd_id id, uid_t uid,
- gid_t gid, struct lov_stripe_md **lsmp);
-
-/* rw.c */
-struct page *ll_getpage(struct inode *inode, unsigned long offset,
- int create, int locked);
-void ll_truncate(struct inode *inode);
-
-/* super.c */
-void ll_update_inode(struct inode *, struct mds_body *);
-
-/* symlink.c */
-extern struct inode_operations ll_fast_symlink_inode_operations;
-extern struct inode_operations ll_symlink_inode_operations;
-
-/* sysctl.c */
-void ll_sysctl_init(void);
-void ll_sysctl_clean(void);
-
-#endif /* __KERNEL__ */
-
-#include <asm/types.h>
-
-#define LL_IOC_GETFLAGS _IOR ('f', 151, long)
-#define LL_IOC_SETFLAGS _IOW ('f', 152, long)
-#define LL_IOC_CLRFLAGS _IOW ('f', 153, long)
-#define LL_IOC_LOV_SETSTRIPE _IOW ('f', 154, long)
-#define LL_IOC_LOV_GETSTRIPE _IOW ('f', 155, long)
-
-#define O_LOV_DELAY_CREATE 0100000000 /* hopefully this does not conflict */
-
-#define LL_FILE_IGNORE_LOCK 0x00000001
-
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc. <info@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * MDS data structures.
- * See also lustre_idl.h for wire formats of requests.
- *
- */
-
-#ifndef _LUSTRE_MDS_H
-#define _LUSTRE_MDS_H
-
-#ifdef __KERNEL__
-
-#include <linux/fs.h>
-#include <linux/lustre_idl.h>
-
-struct ldlm_lock_desc;
-struct mds_obd;
-struct ptlrpc_connection;
-struct ptlrpc_client;
-struct obd_export;
-struct ptlrpc_request;
-struct obd_device;
-
-#define LUSTRE_MDS_NAME "mds"
-#define LUSTRE_MDT_NAME "mdt"
-#define LUSTRE_MDC_NAME "mdc"
-
-struct mds_update_record {
- __u32 ur_fsuid;
- __u32 ur_fsgid;
- __u32 ur_cap;
- __u32 ur_opcode;
- struct ll_fid *ur_fid1;
- struct ll_fid *ur_fid2;
- int ur_namelen;
- char *ur_name;
- int ur_tgtlen;
- char *ur_tgt;
- struct iattr ur_iattr;
- __u64 ur_rdev;
- __u32 ur_mode;
- __u32 ur_uid;
- __u32 ur_gid;
- __u64 ur_time;
-};
-
-#define MDS_LR_CLIENT 8192
-#define MDS_LR_SIZE 128
-
-#define MDS_CLIENT_SLOTS 17
-
-#define MDS_MOUNT_RECOV 2
-
-/* Data stored per server at the head of the last_rcvd file. In le32 order. */
-struct mds_server_data {
- __u8 msd_uuid[37]; /* server UUID */
- __u8 uuid_padding[3]; /* unused */
- __u64 msd_last_rcvd; /* last completed transaction ID */
- __u64 msd_mount_count; /* MDS incarnation number */
- __u8 padding[512 - 56];
-};
-
-/* Data stored per client in the last_rcvd file. In le32 order. */
-struct mds_client_data {
- __u8 mcd_uuid[37]; /* client UUID */
- __u8 uuid_padding[3]; /* unused */
- __u64 mcd_last_rcvd; /* last completed transaction ID */
- __u64 mcd_mount_count; /* MDS incarnation number */
- __u64 mcd_last_xid; /* client RPC xid for the last transaction */
- __u8 padding[MDS_LR_SIZE - 64];
-};
-
-/* In-memory access to client data from MDS struct */
-struct mds_export_data {
- struct list_head med_open_head;
- spinlock_t med_open_lock;
- struct mds_client_data *med_mcd;
- int med_off;
-};
-
-/* file data for open files on MDS */
-struct mds_file_data {
- struct list_head mfd_list;
- struct lustre_handle mfd_clienthandle;
- __u64 mfd_servercookie;
- struct file *mfd_file;
-};
-
-/* mds/mds_reint.c */
-int mds_reint_rec(struct mds_update_record *r, int offset,
- struct ptlrpc_request *req);
-
-/* lib/mds_updates.c */
-void mds_unpack_body(struct mds_body *b);
-void mds_unpack_fid(struct ll_fid *fid);
-void mds_pack_fid(struct ll_fid *fid);
-void mds_pack_req_body(struct ptlrpc_request *);
-void mds_pack_rep_body(struct ptlrpc_request *);
-int mds_update_unpack(struct ptlrpc_request *, int offset,
- struct mds_update_record *);
-
-void mds_readdir_pack(struct ptlrpc_request *req, __u64 offset,
- obd_id ino, int type);
-void mds_getattr_pack(struct ptlrpc_request *req, int offset,
- struct inode *inode, const char *name, int namelen);
-void mds_setattr_pack(struct ptlrpc_request *, int offset, struct inode *,
- struct iattr *, const char *name, int namelen);
-void mds_create_pack(struct ptlrpc_request *, int offset, struct inode *dir,
- __u32 mode, __u64 rdev, __u32 uid, __u32 gid, __u64 time,
- const char *name, int namelen, const void *data,
- int datalen);
-void mds_unlink_pack(struct ptlrpc_request *, int offset, struct inode *inode,
- struct inode *child, __u32 mode, const char *name,
- int namelen);
-void mds_link_pack(struct ptlrpc_request *, int offset, struct inode *ino,
- struct inode *dir, const char *name, int namelen);
-void mds_rename_pack(struct ptlrpc_request *, int offset, struct inode *srcdir,
- struct inode *tgtdir, const char *name, int namelen,
- const char *tgt, int tgtlen);
-void mds_pack_inode2fid(struct ll_fid *fid, struct inode *inode);
-void mds_pack_inode2body(struct mds_body *body, struct inode *inode);
-
-/* mds/handler.c */
-struct dentry *mds_name2locked_dentry(struct obd_device *, struct dentry *dir,
- struct vfsmount **mnt, char *name,
- int namelen, int lock_mode,
- struct lustre_handle *lockh,
- int dir_lock_mode);
-struct dentry *mds_fid2locked_dentry(struct obd_device *obd, struct ll_fid *fid,
- struct vfsmount **mnt, int lock_mode,
- struct lustre_handle *lockh);
-struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid,
- struct vfsmount **mnt);
-int mds_reint(struct ptlrpc_request *req, int offset);
-int mds_pack_md(struct mds_obd *mds, struct ptlrpc_request *req,
- int offset, struct mds_body *body, struct inode *inode);
-
-/* mdc/mdc_request.c */
-int mdc_enqueue(struct lustre_handle *conn, int lock_type,
- struct lookup_intent *it, int lock_mode, struct inode *dir,
- struct dentry *de, struct lustre_handle *lockh, char *tgt,
- int tgtlen, void *data, int datalen);
-int mdc_cancel_unused(struct lustre_handle *conn, struct inode *, int flags);
-int mdc_getlovinfo(struct obd_device *obd, struct lustre_handle *mdc_connh,
- struct ptlrpc_request **request);
-int mdc_getstatus(struct lustre_handle *conn, struct ll_fid *rootfid);
-int mdc_getattr(struct lustre_handle *conn,
- obd_id ino, int type, unsigned long valid, size_t ea_size,
- struct ptlrpc_request **request);
-int mdc_setattr(struct lustre_handle *conn,
- struct inode *, struct iattr *iattr, struct ptlrpc_request **);
-int mdc_open(struct lustre_handle *conn, obd_id ino, int type, int flags,
- struct lov_mds_md *lmm, int lmm_size, struct lustre_handle *fh,
- struct ptlrpc_request **);
-int mdc_close(struct lustre_handle *conn, obd_id ino, int type,
- struct lustre_handle *fh, struct ptlrpc_request **req);
-int mdc_readpage(struct lustre_handle *conn, obd_id ino,
- int type, __u64 offset, char *addr, struct ptlrpc_request **);
-int mdc_create(struct lustre_handle *conn,
- struct inode *dir, const char *name, int namelen,
- const void *data, int datalen, int mode, __u32 uid, __u32 gid,
- __u64 time, __u64 rdev, struct ptlrpc_request **);
-int mdc_unlink(struct lustre_handle *, struct inode *dir, struct inode *child,
- __u32 mode, const char *name, int namelen,
- struct ptlrpc_request **);
-int mdc_link(struct lustre_handle *conn,
- struct dentry *src, struct inode *dir, const char *name,
- int namelen, struct ptlrpc_request **);
-int mdc_rename(struct lustre_handle *conn,
- struct inode *src, struct inode *tgt, const char *old,
- int oldlen, const char *new, int newlen,
- struct ptlrpc_request **);
-int mdc_create_client(obd_uuid_t uuid, struct ptlrpc_client *cl);
-
-/* Store the generation of a newly-created inode in |req| for replay. */
-void mdc_store_inode_generation(struct ptlrpc_request *req, int reqoff,
- int repoff);
-
-int mds_client_add(struct mds_obd *mds, struct mds_export_data *med,
- int cl_off);
-int mds_client_free(struct obd_export *exp);
-
-/* mds/mds_fs.c */
-struct mds_fs_operations {
- struct module *fs_owner;
- void *(* fs_start)(struct inode *inode, int op);
- int (* fs_commit)(struct inode *inode, void *handle);
- int (* fs_setattr)(struct dentry *dentry, void *handle,
- struct iattr *iattr);
- int (* fs_set_md)(struct inode *inode, void *handle,
- struct lov_mds_md *md, int size);
- int (* fs_get_md)(struct inode *inode, struct lov_mds_md *md,
- int size);
- ssize_t (* fs_readpage)(struct file *file, char *buf, size_t count,
- loff_t *offset);
- void (* fs_delete_inode)(struct inode *inode);
- void (* cl_delete_inode)(struct inode *inode);
- int (* fs_journal_data)(struct file *file);
- int (* fs_set_last_rcvd)(struct mds_obd *mds, void *handle);
- int (* fs_statfs)(struct super_block *sb, struct statfs *sfs);
-};
-
-extern int mds_register_fs_type(struct mds_fs_operations *op, const char *name);
-extern void mds_unregister_fs_type(const char *name);
-extern int mds_fs_setup(struct obd_device *obddev, struct vfsmount *mnt);
-extern void mds_fs_cleanup(struct obd_device *obddev);
-
-#define MDS_FSOP_UNLINK 1
-#define MDS_FSOP_RMDIR 2
-#define MDS_FSOP_RENAME 3
-#define MDS_FSOP_CREATE 4
-#define MDS_FSOP_MKDIR 5
-#define MDS_FSOP_SYMLINK 6
-#define MDS_FSOP_MKNOD 7
-#define MDS_FSOP_SETATTR 8
-#define MDS_FSOP_LINK 9
-
-#endif /* __KERNEL__ */
-
-/* ioctls for trying requests */
-#define IOC_REQUEST_TYPE 'f'
-#define IOC_REQUEST_MIN_NR 30
-
-#define IOC_REQUEST_GETATTR _IOWR('f', 30, long)
-#define IOC_REQUEST_READPAGE _IOWR('f', 31, long)
-#define IOC_REQUEST_SETATTR _IOWR('f', 32, long)
-#define IOC_REQUEST_CREATE _IOWR('f', 33, long)
-#define IOC_REQUEST_OPEN _IOWR('f', 34, long)
-#define IOC_REQUEST_CLOSE _IOWR('f', 35, long)
-#define IOC_REQUEST_MAX_NR 35
-
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef _LUSTRE_NET_H
-#define _LUSTRE_NET_H
-
-#include <linux/tqueue.h>
-#include <linux/kp30.h>
-// #include <linux/obd.h>
-#include <portals/p30.h>
-#include <linux/lustre_idl.h>
-#include <linux/lustre_ha.h>
-#include <linux/lustre_import.h>
-
-/* The following constants determine how much memory is devoted to
- * buffering in the lustre services.
- *
- * ?_NEVENTS # event queue entries
- *
- * ?_NBUFS # request buffers
- * ?_BUFSIZE # bytes in a single request buffer
- * total memory = ?_NBUFS * ?_BUFSIZE
- *
- * ?_MAXREQSIZE # maximum request service will receive
- * larger messages will get dropped.
- * request buffers are auto-unlinked when less than ?_MAXREQSIZE
- * is left in them.
- */
-
-#define LDLM_NUM_THREADS 4
-#define LDLM_NEVENTS 1024
-#define LDLM_NBUFS 10
-#define LDLM_BUFSIZE (64 * 1024)
-#define LDLM_MAXREQSIZE 1024
-
-#define MDT_NUM_THREADS 8
-#define MDS_NEVENTS 1024
-#define MDS_NBUFS 10
-#define MDS_BUFSIZE (64 * 1024)
-#define MDS_MAXREQSIZE 1024
-
-#define OST_NUM_THREADS 6
-#define OST_NEVENTS min(num_physpages / 16, 32768UL)
-#define OST_NBUFS min(OST_NEVENTS / 128, 256UL)
-#define OST_BUFSIZE ((OST_NEVENTS > 4096UL ? 128 : 64) * 1024)
-#define OST_MAXREQSIZE (8 * 1024)
-
-#define CONN_INVALID 1
-
-struct ptlrpc_connection {
- struct list_head c_link;
- struct lustre_peer c_peer;
- __u8 c_local_uuid[37]; /* XXX do we need this? */
- __u8 c_remote_uuid[37];
-
- __u32 c_generation; /* changes upon new connection */
- __u32 c_epoch; /* changes when peer changes */
- __u32 c_bootcount; /* peer's boot count */
-
- spinlock_t c_lock; /* also protects req->rq_list */
-
- atomic_t c_refcount;
- __u64 c_token;
- __u64 c_remote_conn;
- __u64 c_remote_token;
-
- struct list_head c_delayed_head;/* delayed until post-recovery XXX imp? */
- struct recovd_data c_recovd_data;
-
- struct list_head c_imports;
- struct list_head c_exports;
- struct list_head c_sb_chain;
- __u32 c_flags; // can we indicate INVALID elsewhere?
-};
-
-struct ptlrpc_client {
- __u32 cli_request_portal;
- __u32 cli_reply_portal;
-
- __u32 cli_target_devno;
-
- void *cli_data;
- char *cli_name;
-};
-
-/* state flags of requests */
-#define PTL_RPC_FL_INTR (1 << 0)
-#define PTL_RPC_FL_REPLIED (1 << 1) /* reply was received */
-#define PTL_RPC_FL_SENT (1 << 2)
-#define PTL_BULK_FL_SENT (1 << 3)
-#define PTL_BULK_FL_RCVD (1 << 4)
-#define PTL_RPC_FL_ERR (1 << 5)
-#define PTL_RPC_FL_TIMEOUT (1 << 6)
-#define PTL_RPC_FL_RESEND (1 << 7)
-#define PTL_RPC_FL_RESTART (1 << 8) /* operation must be restarted */
-#define PTL_RPC_FL_FINISHED (1 << 9)
-#define PTL_RPC_FL_RETAIN (1 << 10) /* retain for replay after reply */
-#define PTL_RPC_FL_REPLAY (1 << 11) /* replay upon recovery */
-#define PTL_RPC_FL_ALLOCREP (1 << 12) /* reply buffer allocated */
-
-struct ptlrpc_request {
- int rq_type; /* one of PTL_RPC_MSG_* */
- struct list_head rq_list;
- struct obd_device *rq_obd;
- int rq_status;
- int rq_flags;
- atomic_t rq_refcount;
-
- int rq_request_portal; /* XXX FIXME bug 249 */
- int rq_reply_portal; /* XXX FIXME bug 249 */
-
- int rq_reqlen;
- struct lustre_msg *rq_reqmsg;
-
- int rq_replen;
- struct lustre_msg *rq_repmsg;
- __u64 rq_transno;
- __u64 rq_xid;
-
- int rq_level;
- time_t rq_timeout;
- // void * rq_reply_handle;
- wait_queue_head_t rq_wait_for_rep;
-
- /* incoming reply */
- ptl_md_t rq_reply_md;
- ptl_handle_me_t rq_reply_me_h;
-
- /* outgoing req/rep */
- ptl_md_t rq_req_md;
-
- struct lustre_peer rq_peer; /* XXX see service.c can this be factored away? */
- struct obd_export *rq_export;
- struct ptlrpc_connection *rq_connection;
- struct obd_import *rq_import;
- struct ptlrpc_service *rq_svc;
-
- void (*rq_replay_cb)(struct ptlrpc_request *);
-};
-
-#define DEBUG_REQ(level, req, fmt, args...) \
-do { \
-CDEBUG(level, \
- "@@@ " fmt " req x"LPD64"/t"LPD64" o%d->%s:%d lens %d/%d ref %d fl " \
- "%x\n" , ## args, req->rq_xid, req->rq_transno, \
- req->rq_reqmsg ? req->rq_reqmsg->opc : -1, \
- req->rq_connection ? (char *)req->rq_connection->c_remote_uuid : "<?>", \
- (req->rq_import && req->rq_import->imp_client) ? \
- req->rq_import->imp_client->cli_request_portal : -1, \
- req->rq_reqlen, req->rq_replen, req->rq_refcount, req->rq_flags); \
-} while (0)
-
-struct ptlrpc_bulk_page {
- struct ptlrpc_bulk_desc *bp_desc;
- struct list_head bp_link;
- void *bp_buf;
- int bp_buflen;
- struct page *bp_page;
- __u32 bp_xid;
- __u32 bp_flags;
- struct dentry *bp_dentry;
- int (*bp_cb)(struct ptlrpc_bulk_page *);
-};
-
-
-struct ptlrpc_bulk_desc {
- struct list_head bd_set_chain; /* entry in obd_brw_set */
- struct obd_brw_set *bd_brw_set;
- int bd_flags;
- struct ptlrpc_connection *bd_connection;
- struct ptlrpc_client *bd_client;
- __u32 bd_portal;
- struct lustre_handle bd_conn;
- void (*bd_ptl_ev_hdlr)(struct ptlrpc_bulk_desc *);
-
- wait_queue_head_t bd_waitq;
- struct list_head bd_page_list;
- __u32 bd_page_count;
- atomic_t bd_refcount;
- void *bd_desc_private;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
- struct work_struct bd_queue;
-#else
- struct tq_struct bd_queue;
-#endif
-
- ptl_md_t bd_md;
- ptl_handle_md_t bd_md_h;
- ptl_handle_me_t bd_me_h;
-
- atomic_t bd_source_callback_count;
-
- struct iovec bd_iov[16]; /* self-sized pre-allocated iov */
-};
-
-struct ptlrpc_thread {
- struct list_head t_link;
-
- __u32 t_flags;
- wait_queue_head_t t_ctl_waitq;
-};
-
-struct ptlrpc_request_buffer_desc {
- struct list_head rqbd_list;
- struct ptlrpc_service *rqbd_service;
- ptl_handle_me_t rqbd_me_h;
- atomic_t rqbd_refcount;
- char *rqbd_buffer;
-};
-
-struct ptlrpc_service {
- time_t srv_time;
- time_t srv_timeout;
-
- /* incoming request buffers */
- /* FIXME: perhaps a list of EQs, if multiple NIs are used? */
-
- __u32 srv_max_req_size; /* biggest request to receive */
- __u32 srv_buf_size; /* # bytes in a request buffer */
- struct list_head srv_rqbds; /* all the request buffer descriptors */
- __u32 srv_nrqbds; /* # request buffers */
- atomic_t srv_nrqbds_receiving; /* # request buffers posted for input */
-
- __u32 srv_req_portal;
- __u32 srv_rep_portal;
-
- __u32 srv_xid;
-
- /* event queue */
- ptl_handle_eq_t srv_eq_h;
-
- struct lustre_peer srv_self;
-
- wait_queue_head_t srv_waitq; /* all threads sleep on this */
-
- spinlock_t srv_lock;
- struct list_head srv_threads;
- int (*srv_handler)(struct ptlrpc_request *req);
- char *srv_name; /* only statically allocated strings here; we don't clean them */
-};
-
-static inline void ptlrpc_hdl2req(struct ptlrpc_request *req,
- struct lustre_handle *h)
-{
- req->rq_reqmsg->addr = h->addr;
- req->rq_reqmsg->cookie = h->cookie;
-}
-
-typedef void (*bulk_callback_t)(struct ptlrpc_bulk_desc *, void *);
-
-typedef int (*svc_handler_t)(struct ptlrpc_request *req);
-
-/* rpc/connection.c */
-void ptlrpc_readdress_connection(struct ptlrpc_connection *, obd_uuid_t uuid);
-struct ptlrpc_connection *ptlrpc_get_connection(struct lustre_peer *peer,
- obd_uuid_t uuid);
-int ptlrpc_put_connection(struct ptlrpc_connection *c);
-struct ptlrpc_connection *ptlrpc_connection_addref(struct ptlrpc_connection *);
-void ptlrpc_init_connection(void);
-void ptlrpc_cleanup_connection(void);
-
-/* rpc/niobuf.c */
-int ptlrpc_check_bulk_sent(struct ptlrpc_bulk_desc *bulk);
-int ptlrpc_check_bulk_received(struct ptlrpc_bulk_desc *bulk);
-int ptlrpc_send_bulk(struct ptlrpc_bulk_desc *);
-int ptlrpc_register_bulk(struct ptlrpc_bulk_desc *);
-int ptlrpc_abort_bulk(struct ptlrpc_bulk_desc *bulk);
-struct obd_brw_set *obd_brw_set_new(void);
-void obd_brw_set_add(struct obd_brw_set *, struct ptlrpc_bulk_desc *);
-void obd_brw_set_free(struct obd_brw_set *);
-
-int ptlrpc_reply(struct ptlrpc_service *svc, struct ptlrpc_request *req);
-int ptlrpc_error(struct ptlrpc_service *svc, struct ptlrpc_request *req);
-void ptlrpc_resend_req(struct ptlrpc_request *request);
-int ptl_send_rpc(struct ptlrpc_request *request);
-void ptlrpc_link_svc_me(struct ptlrpc_request_buffer_desc *rqbd);
-
-/* rpc/client.c */
-void ptlrpc_init_client(int req_portal, int rep_portal, char *name,
- struct ptlrpc_client *);
-void ptlrpc_cleanup_client(struct obd_import *imp);
-__u8 *ptlrpc_req_to_uuid(struct ptlrpc_request *req);
-struct ptlrpc_connection *ptlrpc_uuid_to_connection(obd_uuid_t uuid);
-
-int ll_brw_sync_wait(struct obd_brw_set *, int phase);
-
-int ptlrpc_queue_wait(struct ptlrpc_request *req);
-void ptlrpc_continue_req(struct ptlrpc_request *req);
-int ptlrpc_replay_req(struct ptlrpc_request *req);
-void ptlrpc_restart_req(struct ptlrpc_request *req);
-
-struct ptlrpc_request *ptlrpc_prep_req(struct obd_import *imp, int opcode,
- int count, int *lengths, char **bufs);
-void ptlrpc_free_req(struct ptlrpc_request *request);
-void ptlrpc_req_finished(struct ptlrpc_request *request);
-struct ptlrpc_bulk_desc *ptlrpc_prep_bulk(struct ptlrpc_connection *);
-void ptlrpc_free_bulk(struct ptlrpc_bulk_desc *bulk);
-struct ptlrpc_bulk_page *ptlrpc_prep_bulk_page(struct ptlrpc_bulk_desc *desc);
-void ptlrpc_free_bulk_page(struct ptlrpc_bulk_page *page);
-
-/* rpc/service.c */
-struct ptlrpc_service *
-ptlrpc_init_svc(__u32 nevents, __u32 nbufs, __u32 bufsize, __u32 max_req_size,
- int req_portal, int rep_portal,
- obd_uuid_t uuid, svc_handler_t, char *name);
-void ptlrpc_stop_all_threads(struct ptlrpc_service *svc);
-int ptlrpc_start_thread(struct obd_device *dev, struct ptlrpc_service *svc,
- char *name);
-int ptlrpc_unregister_service(struct ptlrpc_service *service);
-
-struct ptlrpc_svc_data {
- char *name;
- struct ptlrpc_service *svc;
- struct ptlrpc_thread *thread;
- struct obd_device *dev;
-};
-
-/* rpc/pack_generic.c */
-int lustre_pack_msg(int count, int *lens, char **bufs, int *len,
- struct lustre_msg **msg);
-int lustre_msg_size(int count, int *lengths);
-int lustre_unpack_msg(struct lustre_msg *m, int len);
-void *lustre_msg_buf(struct lustre_msg *m, int n);
-
-static inline void ptlrpc_bulk_decref(struct ptlrpc_bulk_desc *desc)
-{
- if (atomic_dec_and_test(&desc->bd_refcount)) {
- CDEBUG(D_PAGE, "Released last ref on %p, freeing\n", desc);
- ptlrpc_free_bulk(desc);
- } else {
- CDEBUG(D_PAGE, "%p -> %d\n", desc,
- atomic_read(&desc->bd_refcount));
- }
-}
-
-static inline void ptlrpc_bulk_addref(struct ptlrpc_bulk_desc *desc)
-{
- atomic_inc(&desc->bd_refcount);
- CDEBUG(D_PAGE, "Set refcount of %p to %d\n", desc,
- atomic_read(&desc->bd_refcount));
-}
-
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-
-#ifndef __OBD_H
-#define __OBD_H
-
-struct lov_oinfo { /* per-child structure */
- __u64 loi_id; /* object ID on the target OST */
- struct lustre_handle *loi_handle; /* handle for object on OST */
- int loi_ost_idx; /* OST stripe index in lmd_objects array */
-};
-
-struct lov_stripe_md {
- __u32 lsm_magic;
- __u64 lsm_object_id; /* lov object id */
- __u64 lsm_stripe_size; /* size of the stripe */
- __u32 lsm_stripe_pattern; /* per-lov object stripe pattern */
- int lsm_stripe_offset; /* offset of first stripe in lmd_objects */
- int lsm_stripe_count; /* how many objects are being striped on */
- struct lov_oinfo lsm_oinfo[0];
-};
-
-#ifdef __KERNEL__
-# include <linux/fs.h>
-# include <linux/list.h>
-# include <linux/smp_lock.h>
-# include <linux/proc_fs.h>
-
-# include <linux/lustre_lib.h>
-# include <linux/lustre_idl.h>
-# include <linux/lustre_mds.h>
-# include <linux/lustre_export.h>
-
-struct obd_type {
- struct list_head typ_chain;
- struct obd_ops *typ_ops;
- struct proc_dir_entry *typ_procroot;
- char *typ_name;
- int typ_refcnt;
-};
-
-struct brw_page {
- struct page *pg;
- obd_size count;
- obd_off off;
- obd_flag flag;
-};
-
-/* Individual type definitions */
-
-struct ext2_obd {
- struct super_block *e2_sb;
- struct vfsmount *e2_vfsmnt;
-};
-
-struct obd_ucred {
- __u32 ouc_fsuid;
- __u32 ouc_fsgid;
- __u32 ouc_cap;
-};
-
-#define OBD_RUN_CTXT_MAGIC 0xC0FFEEAA
-#define OBD_CTXT_DEBUG /* development-only debugging */
-struct obd_run_ctxt {
- struct vfsmount *pwdmnt;
- struct dentry *pwd;
- mm_segment_t fs;
- __u32 fsuid;
- __u32 fsgid;
- __u32 cap;
-#ifdef OBD_CTXT_DEBUG
- __u32 magic;
-#endif
-};
-
-
-#ifdef OBD_CTXT_DEBUG
-#define OBD_SET_CTXT_MAGIC(ctxt) (ctxt)->magic = OBD_RUN_CTXT_MAGIC
-#else
-#define OBD_SET_CTXT_MAGIC(ctxt) do {} while(0)
-#endif
-
-struct filter_obd {
- char *fo_fstype;
- struct super_block *fo_sb;
- struct vfsmount *fo_vfsmnt;
- struct obd_run_ctxt fo_ctxt;
- struct dentry *fo_dentry_O;
- struct dentry *fo_dentry_O_mode[16];
- spinlock_t fo_objidlock; /* protects fo_lastobjid increment */
- __u64 fo_lastobjid;
- struct file_operations *fo_fop;
- struct inode_operations *fo_iop;
- struct address_space_operations *fo_aops;
- struct list_head fo_export_list;
- spinlock_t fo_fddlock; /* protects setting dentry->d_fsdata */
-};
-
-struct mds_server_data;
-
-struct client_obd {
- struct obd_import cl_import;
- struct semaphore cl_sem;
- int cl_conn_count;
- obd_uuid_t cl_target_uuid; /* XXX -> lustre_name */
- /* max_mds_easize is purely a performance thing so we don't have to
- * call obd_size_wiremd() all the time. */
- int cl_max_mds_easize;
- struct obd_device *cl_containing_lov;
-};
-
-#define IOC_OSC_TYPE 'h'
-#define IOC_OSC_MIN_NR 20
-#define IOC_OSC_REGISTER_LOV _IOWR('h', 20, struct obd_device *)
-#define IOC_OSC_MAX_NR 50
-
-struct mds_obd {
- struct ptlrpc_service *mds_service;
-
- char *mds_fstype;
- struct super_block *mds_sb;
- struct super_operations *mds_sop;
- struct vfsmount *mds_vfsmnt;
- struct obd_run_ctxt mds_ctxt;
- struct file_operations *mds_fop;
- struct inode_operations *mds_iop;
- struct address_space_operations *mds_aops;
- struct mds_fs_operations *mds_fsops;
-
- int mds_max_mdsize;
- struct file *mds_rcvd_filp;
- struct semaphore mds_transno_sem;
- __u64 mds_last_committed;
- __u64 mds_last_rcvd;
- __u64 mds_mount_count;
- struct ll_fid mds_rootfid;
- struct mds_server_data *mds_server_data;
-
- wait_queue_head_t mds_next_transno_waitq;
- __u64 mds_next_recovery_transno;
- int mds_recoverable_clients;
- struct list_head mds_recovery_queue;
- struct list_head mds_delayed_reply_queue;
- spinlock_t mds_processing_task_lock;
- pid_t mds_processing_task;
-};
-
-struct ldlm_obd {
- struct ptlrpc_service *ldlm_cb_service;
- struct ptlrpc_service *ldlm_cancel_service;
- struct ptlrpc_client *ldlm_client;
- struct ptlrpc_connection *ldlm_server_conn;
-};
-
-struct echo_obd {
- char *eo_fstype;
- struct obdo oa;
- spinlock_t eo_lock;
- __u64 eo_lastino;
- atomic_t eo_getattr;
- atomic_t eo_setattr;
- atomic_t eo_create;
- atomic_t eo_destroy;
- atomic_t eo_prep;
- atomic_t eo_read;
- atomic_t eo_write;
-};
-
-struct recovd_obd {
- spinlock_t recovd_lock;
- struct list_head recovd_managed_items; /* items managed */
- struct list_head recovd_troubled_items; /* items in recovery */
-
- wait_queue_head_t recovd_recovery_waitq;
- wait_queue_head_t recovd_ctl_waitq;
- wait_queue_head_t recovd_waitq;
- struct task_struct *recovd_thread;
- __u32 recovd_state;
-};
-
-struct trace_obd {
- struct obdtrace_opstats *stats;
-};
-
-#if 0
-struct snap_obd {
- unsigned int snap_index; /* which snapshot index are we accessing */
- int snap_tableno;
-};
-
-#endif
-
-struct ost_obd {
- struct ptlrpc_service *ost_service;
- struct lustre_handle ost_conn; /* the local connection to the OBD */
-};
-
-struct echo_client_obd {
- struct lustre_handle conn; /* the local connection to osc/lov */
-};
-
-struct lov_tgt_desc {
- obd_uuid_t uuid;
- struct lustre_handle conn;
- int active; /* is this target available for requests, etc */
-};
-
-struct lov_obd {
- spinlock_t lov_lock;
- struct obd_device *mdcobd;
- struct lov_desc desc;
- int bufsize;
- int refcount;
- struct lov_tgt_desc *tgts;
-};
-
-struct niobuf_local {
- __u64 offset;
- __u32 len;
- __u32 xid;
- __u32 flags;
- void *addr;
- struct page *page;
- void *target_private;
- struct dentry *dentry;
-};
-
-#define N_LOCAL_TEMP_PAGE 0x00000001
-
-/* corresponds to one of the obd's */
-struct obd_device {
- struct obd_type *obd_type;
-
- /* common and UUID name of this device */
- char *obd_name;
- obd_uuid_t obd_uuid;
-
- int obd_minor;
- int obd_flags;
- struct proc_dir_entry *obd_proc_entry;
- struct list_head obd_exports;
- struct list_head obd_imports;
- struct ldlm_namespace *obd_namespace;
- struct ptlrpc_client obd_ldlm_client; /* XXX OST/MDS only */
- /* a spinlock is OK for what we do now, may need a semaphore later */
- spinlock_t obd_dev_lock;
- union {
- struct ext2_obd ext2;
- struct filter_obd filter;
- struct mds_obd mds;
- struct client_obd cli;
- struct ost_obd ost;
- struct echo_client_obd echo_client;;
- // struct osc_obd osc;
- struct ldlm_obd ldlm;
- struct echo_obd echo;
- struct recovd_obd recovd;
- struct trace_obd trace;
- struct lov_obd lov;
-#if 0
- struct snap_obd snap;
-#endif
- } u;
- /* Fields used by LProcFS */
- unsigned int cntr_mem_size;
- void* counters;
-};
-
-struct obd_ops {
- int (*o_iocontrol)(unsigned int cmd, struct lustre_handle *, int len,
- void *karg, void *uarg);
- int (*o_get_info)(struct lustre_handle *, obd_count keylen, void *key,
- obd_count *vallen, void **val);
- int (*o_set_info)(struct lustre_handle *, obd_count keylen, void *key,
- obd_count vallen, void *val);
- int (*o_attach)(struct obd_device *dev, obd_count len, void *data);
- int (*o_detach)(struct obd_device *dev);
- int (*o_setup) (struct obd_device *dev, obd_count len, void *data);
- int (*o_cleanup)(struct obd_device *dev);
- int (*o_connect)(struct lustre_handle *conn, struct obd_device *src,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover);
- int (*o_disconnect)(struct lustre_handle *conn);
-
-
- int (*o_statfs)(struct lustre_handle *conn, struct obd_statfs *osfs);
- int (*o_packmd)(struct lustre_handle *, struct lov_mds_md **wire_tgt,
- struct lov_stripe_md *mem_src);
- int (*o_unpackmd)(struct lustre_handle *,
- struct lov_stripe_md **mem_tgt,
- struct lov_mds_md *wire_src);
- int (*o_preallocate)(struct lustre_handle *, obd_count *req,
- obd_id *ids);
- int (*o_create)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md **ea);
- int (*o_destroy)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea);
- int (*o_setattr)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea);
- int (*o_getattr)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea);
- int (*o_open)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea);
- int (*o_close)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea);
- int (*o_brw)(int rw, struct lustre_handle *conn,
- struct lov_stripe_md *ea, obd_count oa_bufs,
- struct brw_page *pgarr, struct obd_brw_set *);
- int (*o_punch)(struct lustre_handle *conn, struct obdo *tgt,
- struct lov_stripe_md *ea, obd_size count,
- obd_off offset);
- int (*o_sync)(struct lustre_handle *conn, struct obdo *tgt,
- obd_size count, obd_off offset);
- int (*o_migrate)(struct lustre_handle *conn, struct obdo *dst,
- struct obdo *src, obd_size count, obd_off offset);
- int (*o_copy)(struct lustre_handle *dstconn, struct obdo *dst,
- struct lustre_handle *srconn, struct obdo *src,
- obd_size count, obd_off offset);
- int (*o_iterate)(struct lustre_handle *conn,
- int (*)(obd_id, obd_gr, void *),
- obd_id *startid, obd_gr group, void *data);
- int (*o_preprw)(int cmd, struct lustre_handle *conn,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_remote *remote,
- struct niobuf_local *local, void **desc_private);
- int (*o_commitrw)(int cmd, struct lustre_handle *conn,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_local *local,
- void *desc_private);
- int (*o_enqueue)(struct lustre_handle *conn, struct lov_stripe_md *md,
- struct lustre_handle *parent_lock,
- __u32 type, void *cookie, int cookielen, __u32 mode,
- int *flags, void *cb, void *data, int datalen,
- struct lustre_handle *lockh);
- int (*o_cancel)(struct lustre_handle *, struct lov_stripe_md *md,
- __u32 mode, struct lustre_handle *);
- int (*o_cancel_unused)(struct lustre_handle *, struct lov_stripe_md *,
- int local_only);
-
-};
-
-static inline void *mds_fs_start(struct mds_obd *mds, struct inode *inode,
- int op)
-{
- return mds->mds_fsops->fs_start(inode, op);
-}
-
-static inline int mds_fs_commit(struct mds_obd *mds, struct inode *inode,
- void *handle)
-{
- return mds->mds_fsops->fs_commit(inode, handle);
-}
-
-static inline int mds_fs_setattr(struct mds_obd *mds, struct dentry *dentry,
- void *handle, struct iattr *iattr)
-{
- int rc;
- /*
- * NOTE: we probably don't need to take i_sem here when changing
- * ATTR_SIZE because the MDS never needs to truncate a file.
- * The ext2/ext3 code never truncates a directory, and files
- * stored on the MDS are entirely sparse (no data blocks).
- * If we do need to get it, we can do it here.
- */
- lock_kernel();
- rc = mds->mds_fsops->fs_setattr(dentry, handle, iattr);
- unlock_kernel();
-
- return rc;
-}
-
-static inline int mds_fs_set_md(struct mds_obd *mds, struct inode *inode,
- void *handle, struct lov_mds_md *md,
- int size)
-{
- return mds->mds_fsops->fs_set_md(inode, handle, md, size);
-}
-
-static inline int mds_fs_get_md(struct mds_obd *mds, struct inode *inode,
- struct lov_mds_md *md, int size)
-{
- return mds->mds_fsops->fs_get_md(inode, md, size);
-}
-
-static inline ssize_t mds_fs_readpage(struct mds_obd *mds, struct file *file,
- char *buf, size_t count, loff_t *offset)
-{
- return mds->mds_fsops->fs_readpage(file, buf, count, offset);
-}
-
-/* Set up callback to update mds->mds_last_committed with the current
- * value of mds->mds_last_recieved when this transaction is on disk.
- */
-static inline int mds_fs_set_last_rcvd(struct mds_obd *mds, void *handle)
-{
- return mds->mds_fsops->fs_set_last_rcvd(mds, handle);
-}
-
-/* Enable data journaling on the given file */
-static inline ssize_t mds_fs_journal_data(struct mds_obd *mds,
- struct file *file)
-{
- return mds->mds_fsops->fs_journal_data(file);
-}
-
-static inline int mds_fs_statfs(struct mds_obd *mds, struct statfs *sfs)
-{
- if (mds->mds_fsops->fs_statfs)
- return mds->mds_fsops->fs_statfs(mds->mds_sb, sfs);
-
- return vfs_statfs(mds->mds_sb, sfs);
-}
-#endif /* __KERNEL */
-#endif /* __OBD_H */
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __LINUX_CLASS_OBD_H
-#define __LINUX_CLASS_OBD_H
-
-#ifndef __KERNEL__
-# include <stdint.h>
-# define __KERNEL__
-# include <linux/list.h>
-# undef __KERNEL__
-#else
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/time.h>
-
-#include <linux/obd_support.h>
-#include <linux/obd.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_idl.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_dlm.h>
-#include <linux/lprocfs_status.h>
-#endif
-
-
-/* OBD Device Declarations */
-#define MAX_OBD_DEVICES 128
-extern struct obd_device obd_dev[MAX_OBD_DEVICES];
-
-#define OBD_ATTACHED 0x1
-#define OBD_SET_UP 0x2
-
-/* OBD Operations Declarations */
-
-#ifdef __KERNEL__
-static inline int obd_check_conn(struct lustre_handle *conn)
-{
- struct obd_device *obd;
- if (!conn) {
- CERROR("NULL conn\n");
- RETURN(-ENOTCONN);
- }
- obd = class_conn2obd(conn);
- if (!obd) {
- CERROR("NULL obd\n");
- RETURN(-ENODEV);
- }
-
- if (!obd->obd_flags & OBD_ATTACHED ) {
- CERROR("obd %d not attached\n", obd->obd_minor);
- RETURN(-ENODEV);
- }
-
- if (!obd->obd_flags & OBD_SET_UP) {
- CERROR("obd %d not setup\n", obd->obd_minor);
- RETURN(-ENODEV);
- }
-
- if (!obd->obd_type) {
- CERROR("obd %d not typed\n", obd->obd_minor);
- RETURN(-ENODEV);
- }
-
- if (!obd->obd_type->typ_ops) {
- CERROR("obd_check_conn: obd %d no operations\n",
- obd->obd_minor);
- RETURN(-EOPNOTSUPP);
- }
- return 0;
-}
-
-
-#define OBT(dev) (dev)->obd_type
-#define OBP(dev, op) (dev)->obd_type->typ_ops->o_ ## op
-
-#define OBD_CHECK_SETUP(conn, exp) \
-do { \
- if (!(conn)) { \
- CERROR("NULL connection\n"); \
- RETURN(-EINVAL); \
- } \
- \
- exp = class_conn2export(conn); \
- if (!(exp)) { \
- CERROR("No export\n"); \
- RETURN(-EINVAL); \
- } \
- \
- if (!((exp)->exp_obd->obd_flags & OBD_SET_UP)) { \
- CERROR("Device %d not setup\n", \
- (exp)->exp_obd->obd_minor); \
- RETURN(-EINVAL); \
- } \
-} while (0)
-
-#define OBD_CHECK_DEVSETUP(obd) \
-do { \
- if (!(obd)) { \
- CERROR("NULL device\n"); \
- RETURN(-EINVAL); \
- } \
- \
- if (!((obd)->obd_flags & OBD_SET_UP)) { \
- CERROR("Device %d not setup\n", \
- (obd)->obd_minor); \
- RETURN(-EINVAL); \
- } \
-} while (0)
-
-#define OBD_CHECK_OP(obd, op) \
-do { \
- if (!OBP((obd), op)) { \
- CERROR("obd_" #op ": dev %d no operation\n", \
- obd->obd_minor); \
- RETURN(-EOPNOTSUPP); \
- } \
-} while (0)
-
-static inline int obd_get_info(struct lustre_handle *conn, obd_count keylen,
- void *key, obd_count *vallen, void **val)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, get_info);
-
- rc = OBP(exp->exp_obd, get_info)(conn, keylen, key, vallen, val);
- RETURN(rc);
-}
-
-static inline int obd_set_info(struct lustre_handle *conn, obd_count keylen,
- void *key, obd_count vallen, void *val)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, set_info);
-
- rc = OBP(exp->exp_obd, set_info)(conn, keylen, key, vallen, val);
- RETURN(rc);
-}
-
-static inline int obd_setup(struct obd_device *obd, int datalen, void *data)
-{
- int rc;
- ENTRY;
-
- OBD_CHECK_OP(obd, setup);
-
- rc = OBP(obd, setup)(obd, datalen, data);
- RETURN(rc);
-}
-
-static inline int obd_cleanup(struct obd_device *obd)
-{
- int rc;
- ENTRY;
-
- OBD_CHECK_DEVSETUP(obd);
- OBD_CHECK_OP(obd, cleanup);
-
- rc = OBP(obd, cleanup)(obd);
- RETURN(rc);
-}
-
-/* Pack an in-memory MD struct for sending to the MDS and/or disk.
- * Returns +ve size of packed MD (0 for free), or -ve error.
- *
- * If @wire_tgt == NULL, MD size is returned (max size if @mem_src == NULL).
- * If @*wire_tgt != NULL and @mem_src == NULL, @*wire_tgt will be freed.
- * If @*wire_tgt == NULL, it will be allocated
- */
-static inline int obd_packmd(struct lustre_handle *conn,
- struct lov_mds_md **wire_tgt,
- struct lov_stripe_md *mem_src)
-{
- struct obd_export *exp;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, packmd);
-
- RETURN(OBP(exp->exp_obd, packmd)(conn, wire_tgt, mem_src));
-}
-
-static inline int obd_size_wiremd(struct lustre_handle *conn,
- struct lov_stripe_md *mem_src)
-{
- return obd_packmd(conn, NULL, mem_src);
-}
-
-/* helper functions */
-static inline int obd_alloc_wiremd(struct lustre_handle *conn,
- struct lov_mds_md **wire_tgt)
-{
- LASSERT(wire_tgt);
- LASSERT(*wire_tgt == NULL);
- return obd_packmd(conn, wire_tgt, NULL);
-}
-
-static inline int obd_free_wiremd(struct lustre_handle *conn,
- struct lov_mds_md **wire_tgt)
-{
- LASSERT(wire_tgt);
- LASSERT(*wire_tgt);
- return obd_packmd(conn, wire_tgt, NULL);
-}
-
-/* Unpack an MD struct from the MDS and/or disk to in-memory format.
- * Returns +ve size of unpacked MD (0 for free), or -ve error.
- *
- * If @mem_tgt == NULL, MD size is returned (max size if @wire_src == NULL).
- * If @*mem_tgt != NULL and @wire_src == NULL, @*mem_tgt will be freed.
- * If @*mem_tgt == NULL, it will be allocated
- */
-static inline int obd_unpackmd(struct lustre_handle *conn,
- struct lov_stripe_md **mem_tgt,
- struct lov_mds_md *wire_src)
-{
- struct obd_export *exp;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, unpackmd);
-
- RETURN(OBP(exp->exp_obd, unpackmd)(conn, mem_tgt, wire_src));
-}
-
-static inline int obd_size_memmd(struct lustre_handle *conn,
- struct lov_mds_md *wire_src)
-{
- return obd_unpackmd(conn, NULL, wire_src);
-}
-
-/* helper functions */
-static inline int obd_alloc_memmd(struct lustre_handle *conn,
- struct lov_stripe_md **mem_tgt)
-{
- LASSERT(mem_tgt);
- LASSERT(*mem_tgt == NULL);
- return obd_unpackmd(conn, mem_tgt, NULL);
-}
-
-static inline int obd_free_memmd(struct lustre_handle *conn,
- struct lov_stripe_md **mem_tgt)
-{
- LASSERT(mem_tgt);
- LASSERT(*mem_tgt);
- return obd_unpackmd(conn, mem_tgt, NULL);
-}
-
-static inline int obd_create(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md **ea)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, create);
-
- rc = OBP(exp->exp_obd, create)(conn, obdo, ea);
- RETURN(rc);
-}
-
-static inline int obd_destroy(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md *ea)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, destroy);
-
- rc = OBP(exp->exp_obd, destroy)(conn, obdo, ea);
- RETURN(rc);
-}
-
-static inline int obd_getattr(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md *ea)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, getattr);
-
- rc = OBP(exp->exp_obd, getattr)(conn, obdo, ea);
- RETURN(rc);
-}
-
-static inline int obd_close(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md *ea)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, close);
-
- rc = OBP(exp->exp_obd, close)(conn, obdo, ea);
- RETURN(rc);
-}
-
-static inline int obd_open(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md *ea)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, open);
-
- rc = OBP(exp->exp_obd, open)(conn, obdo, ea);
- RETURN(rc);
-}
-
-static inline int obd_setattr(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md *ea)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, setattr);
-
- rc = OBP(exp->exp_obd, setattr)(conn, obdo, ea);
- RETURN(rc);
-}
-
-static inline int obd_connect(struct lustre_handle *conn,
- struct obd_device *obd, obd_uuid_t cluuid,
- struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- int rc;
- ENTRY;
-
- OBD_CHECK_DEVSETUP(obd);
- OBD_CHECK_OP(obd, connect);
-
- rc = OBP(obd, connect)(conn, obd, cluuid, recovd, recover);
- RETURN(rc);
-}
-
-static inline int obd_disconnect(struct lustre_handle *conn)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, disconnect);
-
- rc = OBP(exp->exp_obd, disconnect)(conn);
- RETURN(rc);
-}
-
-static inline int obd_statfs(struct lustre_handle *conn,struct obd_statfs *osfs)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, statfs);
-
- rc = OBP(exp->exp_obd, statfs)(conn, osfs);
- RETURN(rc);
-}
-
-static inline int obd_punch(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea,
- obd_size start, obd_size end)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, punch);
-
- rc = OBP(exp->exp_obd, punch)(conn, oa, ea, start, end);
- RETURN(rc);
-}
-
-static inline int obd_brw(int cmd, struct lustre_handle *conn,
- struct lov_stripe_md *ea, obd_count oa_bufs,
- struct brw_page *pg, struct obd_brw_set *set)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, brw);
-
- if (!(cmd & OBD_BRW_RWMASK)) {
- CERROR("obd_brw: cmd must be OBD_BRW_READ or OBD_BRW_WRITE\n");
- LBUG();
- }
-
- rc = OBP(exp->exp_obd, brw)(cmd, conn, ea, oa_bufs, pg, set);
- RETURN(rc);
-}
-
-static inline int obd_preprw(int cmd, struct lustre_handle *conn,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_remote *remote,
- struct niobuf_local *local, void **desc_private)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, preprw);
-
- rc = OBP(exp->exp_obd, preprw)(cmd, conn, objcount, obj, niocount,
- remote, local, desc_private);
- RETURN(rc);
-}
-
-static inline int obd_commitrw(int cmd, struct lustre_handle *conn,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_local *local,
- void *desc_private)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, commitrw);
-
- rc = OBP(exp->exp_obd, commitrw)(cmd, conn, objcount, obj, niocount,
- local, desc_private);
- RETURN(rc);
-}
-
-static inline int obd_iocontrol(unsigned int cmd, struct lustre_handle *conn,
- int len, void *karg, void *uarg)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, iocontrol);
-
- rc = OBP(exp->exp_obd, iocontrol)(cmd, conn, len, karg, uarg);
- RETURN(rc);
-}
-
-static inline int obd_enqueue(struct lustre_handle *conn,
- struct lov_stripe_md *ea,
- struct lustre_handle *parent_lock,
- __u32 type, void *cookie, int cookielen,
- __u32 mode, int *flags, void *cb, void *data,
- int datalen, struct lustre_handle *lockh)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, enqueue);
-
- rc = OBP(exp->exp_obd, enqueue)(conn, ea, parent_lock, type,
- cookie, cookielen, mode, flags, cb,
- data, datalen, lockh);
- RETURN(rc);
-}
-
-static inline int obd_cancel(struct lustre_handle *conn,
- struct lov_stripe_md *ea, __u32 mode,
- struct lustre_handle *lockh)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, cancel);
-
- rc = OBP(exp->exp_obd, cancel)(conn, ea, mode, lockh);
- RETURN(rc);
-}
-
-static inline int obd_cancel_unused(struct lustre_handle *conn,
- struct lov_stripe_md *ea, int local)
-{
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- OBD_CHECK_SETUP(conn, exp);
- OBD_CHECK_OP(exp->exp_obd, cancel_unused);
-
- rc = OBP(exp->exp_obd, cancel_unused)(conn, ea, local);
- RETURN(rc);
-}
-
-#endif
-
-/* OBD Metadata Support */
-
-extern int obd_init_caches(void);
-extern void obd_cleanup_caches(void);
-
-static inline struct lustre_handle *obdo_handle(struct obdo *oa)
-{
- return (struct lustre_handle *)&oa->o_inline;
-}
-
-static inline void obd_oa2handle(struct lustre_handle *handle, struct obdo *oa)
-{
- if (oa->o_valid |= OBD_MD_FLHANDLE) {
- struct lustre_handle *oa_handle = obdo_handle(oa);
- memcpy(handle, oa_handle, sizeof(*handle));
- }
-}
-
-static inline void obd_handle2oa(struct obdo *oa, struct lustre_handle *handle)
-{
- if (handle->addr) {
- struct lustre_handle *oa_handle = obdo_handle(oa);
- memcpy(oa_handle, handle, sizeof(*handle));
- oa->o_valid |= OBD_MD_FLHANDLE;
- }
-}
-
-#ifdef __KERNEL__
-/* support routines */
-extern kmem_cache_t *obdo_cachep;
-static inline struct obdo *obdo_alloc(void)
-{
- struct obdo *oa;
-
- oa = kmem_cache_alloc(obdo_cachep, SLAB_KERNEL);
- if (oa == NULL)
- LBUG();
- memset(oa, 0, sizeof (*oa));
-
- return oa;
-}
-
-static inline void obdo_free(struct obdo *oa)
-{
- if (!oa)
- return;
- kmem_cache_free(obdo_cachep, oa);
-}
-
-static inline void obdo_from_iattr(struct obdo *oa, struct iattr *attr)
-{
- unsigned int ia_valid = attr->ia_valid;
-
- if (ia_valid & ATTR_ATIME) {
- oa->o_atime = attr->ia_atime;
- oa->o_valid |= OBD_MD_FLATIME;
- }
- if (ia_valid & ATTR_MTIME) {
- oa->o_mtime = attr->ia_mtime;
- oa->o_valid |= OBD_MD_FLMTIME;
- }
- if (ia_valid & ATTR_CTIME) {
- oa->o_ctime = attr->ia_ctime;
- oa->o_valid |= OBD_MD_FLCTIME;
- }
- if (ia_valid & ATTR_SIZE) {
- oa->o_size = attr->ia_size;
- oa->o_valid |= OBD_MD_FLSIZE;
- }
- if (ia_valid & ATTR_MODE) {
- oa->o_mode = attr->ia_mode;
- oa->o_valid |= OBD_MD_FLTYPE | OBD_MD_FLMODE;
- if (!in_group_p(oa->o_gid) && !capable(CAP_FSETID))
- oa->o_mode &= ~S_ISGID;
- }
- if (ia_valid & ATTR_UID) {
- oa->o_uid = attr->ia_uid;
- oa->o_valid |= OBD_MD_FLUID;
- }
- if (ia_valid & ATTR_GID) {
- oa->o_gid = attr->ia_gid;
- oa->o_valid |= OBD_MD_FLGID;
- }
-}
-
-
-static inline void iattr_from_obdo(struct iattr *attr, struct obdo *oa,
- obd_flag valid)
-{
- memset(attr, 0, sizeof(*attr));
- if (valid & OBD_MD_FLATIME) {
- attr->ia_atime = oa->o_atime;
- attr->ia_valid |= ATTR_ATIME;
- }
- if (valid & OBD_MD_FLMTIME) {
- attr->ia_mtime = oa->o_mtime;
- attr->ia_valid |= ATTR_MTIME;
- }
- if (valid & OBD_MD_FLCTIME) {
- attr->ia_ctime = oa->o_ctime;
- attr->ia_valid |= ATTR_CTIME;
- }
- if (valid & OBD_MD_FLSIZE) {
- attr->ia_size = oa->o_size;
- attr->ia_valid |= ATTR_SIZE;
- }
- if (valid & OBD_MD_FLTYPE) {
- attr->ia_mode = (attr->ia_mode & ~S_IFMT)|(oa->o_mode & S_IFMT);
- attr->ia_valid |= ATTR_MODE;
- }
- if (valid & OBD_MD_FLMODE) {
- attr->ia_mode = (attr->ia_mode & S_IFMT)|(oa->o_mode & ~S_IFMT);
- attr->ia_valid |= ATTR_MODE;
- if (!in_group_p(oa->o_gid) && !capable(CAP_FSETID))
- attr->ia_mode &= ~S_ISGID;
- }
- if (valid & OBD_MD_FLUID)
- {
- attr->ia_uid = oa->o_uid;
- attr->ia_valid |= ATTR_UID;
- }
- if (valid & OBD_MD_FLGID) {
- attr->ia_gid = oa->o_gid;
- attr->ia_valid |= ATTR_GID;
- }
-}
-
-
-/* WARNING: the file systems must take care not to tinker with
- attributes they don't manage (such as blocks). */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#define to_kdev_t(dev) dev
-#define kdev_t_to_nr(dev) dev
-#endif
-
-static inline void obdo_from_inode(struct obdo *dst, struct inode *src,
- obd_flag valid)
-{
-// if (valid & OBD_MD_FLID)
-// dst->o_id = src->i_ino;
- if (valid & OBD_MD_FLATIME)
- dst->o_atime = src->i_atime;
- if (valid & OBD_MD_FLMTIME)
- dst->o_mtime = src->i_mtime;
- if (valid & OBD_MD_FLCTIME)
- dst->o_ctime = src->i_ctime;
- if (valid & OBD_MD_FLSIZE)
- dst->o_size = src->i_size;
- if (valid & OBD_MD_FLBLOCKS) /* allocation of space */
- dst->o_blocks = src->i_blocks;
- if (valid & OBD_MD_FLBLKSZ)
- dst->o_blksize = src->i_blksize;
- if (valid & OBD_MD_FLTYPE)
- dst->o_mode = (dst->o_mode & ~S_IFMT) | (src->i_mode & S_IFMT);
- if (valid & OBD_MD_FLMODE)
- dst->o_mode = (dst->o_mode & S_IFMT) | (src->i_mode & ~S_IFMT);
- if (valid & OBD_MD_FLUID)
- dst->o_uid = src->i_uid;
- if (valid & OBD_MD_FLGID)
- dst->o_gid = src->i_gid;
- if (valid & OBD_MD_FLFLAGS)
- dst->o_flags = src->i_flags;
- if (valid & OBD_MD_FLNLINK)
- dst->o_nlink = src->i_nlink;
- if (valid & OBD_MD_FLGENER)
- dst->o_generation = src->i_generation;
- if (valid & OBD_MD_FLRDEV)
- dst->o_rdev = (__u32)kdev_t_to_nr(src->i_rdev);
-
- dst->o_valid |= (valid & ~OBD_MD_FLID);
-}
-
-static inline void obdo_to_inode(struct inode *dst, struct obdo *src,
- obd_flag valid)
-{
-// if (valid & OBD_MD_FLID)
-// dst->i_ino = src->o_id;
- if (valid & OBD_MD_FLATIME)
- dst->i_atime = src->o_atime;
- if (valid & OBD_MD_FLMTIME)
- dst->i_mtime = src->o_mtime;
- if (valid & OBD_MD_FLCTIME)
- dst->i_ctime = src->o_ctime;
- if (valid & OBD_MD_FLSIZE)
- dst->i_size = src->o_size;
- if (valid & OBD_MD_FLBLOCKS) /* allocation of space */
- dst->i_blocks = src->o_blocks;
- if (valid & OBD_MD_FLBLKSZ)
- dst->i_blksize = src->o_blksize;
- if (valid & OBD_MD_FLTYPE)
- dst->i_mode = (dst->i_mode & ~S_IFMT) | (src->o_mode & S_IFMT);
- if (valid & OBD_MD_FLMODE)
- dst->i_mode = (dst->i_mode & S_IFMT) | (src->o_mode & ~S_IFMT);
- if (valid & OBD_MD_FLUID)
- dst->i_uid = src->o_uid;
- if (valid & OBD_MD_FLGID)
- dst->i_gid = src->o_gid;
- if (valid & OBD_MD_FLFLAGS)
- dst->i_flags = src->o_flags;
- if (valid & OBD_MD_FLNLINK)
- dst->i_nlink = src->o_nlink;
- if (valid & OBD_MD_FLGENER)
- dst->i_generation = src->o_generation;
- if (valid & OBD_MD_FLRDEV)
- dst->i_rdev = to_kdev_t(src->o_rdev);
-}
-#endif
-
-static inline void obdo_cpy_md(struct obdo *dst, struct obdo *src,
- obd_flag valid)
-{
-#ifdef __KERNEL__
- CDEBUG(D_INODE, "src obdo %Ld valid 0x%x, dst obdo %Ld\n",
- (unsigned long long)src->o_id, src->o_valid,
- (unsigned long long)dst->o_id);
-#endif
- if (valid & OBD_MD_FLATIME)
- dst->o_atime = src->o_atime;
- if (valid & OBD_MD_FLMTIME)
- dst->o_mtime = src->o_mtime;
- if (valid & OBD_MD_FLCTIME)
- dst->o_ctime = src->o_ctime;
- if (valid & OBD_MD_FLSIZE)
- dst->o_size = src->o_size;
- if (valid & OBD_MD_FLBLOCKS) /* allocation of space */
- dst->o_blocks = src->o_blocks;
- if (valid & OBD_MD_FLBLKSZ)
- dst->o_blksize = src->o_blksize;
- if (valid & OBD_MD_FLTYPE)
- dst->o_mode = (dst->o_mode & ~S_IFMT) | (src->o_mode & S_IFMT);
- if (valid & OBD_MD_FLMODE)
- dst->o_mode = (dst->o_mode & S_IFMT) | (src->o_mode & ~S_IFMT);
- if (valid & OBD_MD_FLUID)
- dst->o_uid = src->o_uid;
- if (valid & OBD_MD_FLGID)
- dst->o_gid = src->o_gid;
- if (valid & OBD_MD_FLFLAGS)
- dst->o_flags = src->o_flags;
- /*
- if (valid & OBD_MD_FLOBDFLG)
- dst->o_obdflags = src->o_obdflags;
- */
- if (valid & OBD_MD_FLNLINK)
- dst->o_nlink = src->o_nlink;
- if (valid & OBD_MD_FLGENER)
- dst->o_generation = src->o_generation;
- if (valid & OBD_MD_FLRDEV)
- dst->o_rdev = src->o_rdev;
- if (valid & OBD_MD_FLINLINE &&
- src->o_obdflags & OBD_FL_INLINEDATA) {
- memcpy(dst->o_inline, src->o_inline, sizeof(src->o_inline));
- dst->o_obdflags |= OBD_FL_INLINEDATA;
- }
-
- dst->o_valid |= valid;
-}
-
-
-/* returns FALSE if comparison (by flags) is same, TRUE if changed */
-static inline int obdo_cmp_md(struct obdo *dst, struct obdo *src,
- obd_flag compare)
-{
- int res = 0;
-
- if ( compare & OBD_MD_FLATIME )
- res = (res || (dst->o_atime != src->o_atime));
- if ( compare & OBD_MD_FLMTIME )
- res = (res || (dst->o_mtime != src->o_mtime));
- if ( compare & OBD_MD_FLCTIME )
- res = (res || (dst->o_ctime != src->o_ctime));
- if ( compare & OBD_MD_FLSIZE )
- res = (res || (dst->o_size != src->o_size));
- if ( compare & OBD_MD_FLBLOCKS ) /* allocation of space */
- res = (res || (dst->o_blocks != src->o_blocks));
- if ( compare & OBD_MD_FLBLKSZ )
- res = (res || (dst->o_blksize != src->o_blksize));
- if ( compare & OBD_MD_FLTYPE )
- res = (res || (((dst->o_mode ^ src->o_mode) & S_IFMT) != 0));
- if ( compare & OBD_MD_FLMODE )
- res = (res || (((dst->o_mode ^ src->o_mode) & ~S_IFMT) != 0));
- if ( compare & OBD_MD_FLUID )
- res = (res || (dst->o_uid != src->o_uid));
- if ( compare & OBD_MD_FLGID )
- res = (res || (dst->o_gid != src->o_gid));
- if ( compare & OBD_MD_FLFLAGS )
- res = (res || (dst->o_flags != src->o_flags));
- if ( compare & OBD_MD_FLNLINK )
- res = (res || (dst->o_nlink != src->o_nlink));
- if ( compare & OBD_MD_FLGENER )
- res = (res || (dst->o_generation != src->o_generation));
- /* XXX Don't know if thses should be included here - wasn't previously
- if ( compare & OBD_MD_FLINLINE )
- res = (res || memcmp(dst->o_inline, src->o_inline));
- */
- return res;
-}
-
-
-#ifdef __KERNEL__
-/* I'm as embarrassed about this as you are.
- *
- * <shaver> // XXX do not look into _superhack with remaining eye
- * <shaver> // XXX if this were any uglier, I'd get my own show on MTV */
-extern int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c);
-
-int class_register_type(struct obd_ops *ops, struct lprocfs_vars* vars,
- char *nm);
-int class_unregister_type(char *nm);
-int class_name2dev(char *name);
-int class_uuid2dev(char *uuid);
-struct obd_device *class_uuid2obd(char *uuid);
-struct obd_export *class_new_export(struct obd_device *obddev);
-struct obd_type *class_nm_to_type(char* name);
-void class_destroy_export(struct obd_export *exp);
-int class_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid);
-int class_disconnect(struct lustre_handle *conn);
-void class_disconnect_all(struct obd_device *obddev);
-
-/* generic operations shared by various OBD types */
-int class_multi_setup(struct obd_device *obddev, uint32_t len, void *data);
-int class_multi_cleanup(struct obd_device *obddev);
-
-extern void (*class_signal_connection_failure)(struct ptlrpc_connection *);
-
-static inline struct ptlrpc_connection *class_rd2conn(struct recovd_data *rd)
-{
- /* reuse list_entry's member-pointer offset stuff */
- return list_entry(rd, struct ptlrpc_connection, c_recovd_data);
-}
-
-#endif
-
-/* sysctl.c */
-extern void obd_sysctl_init (void);
-extern void obd_sysctl_clean (void);
-
-/* uuid.c */
-typedef __u8 class_uuid_t[16];
-//int class_uuid_parse(obd_uuid_t in, class_uuid_t out);
-void class_uuid_unparse(class_uuid_t in, obd_uuid_t out);
-#endif /* __LINUX_CLASS_OBD_H */
+++ /dev/null
-#ifndef _OBD_ECHO_H
-#define _OBD_ECHO_H
-/*
- * Copyright (C) 2001 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-
-#define OBD_ECHO_DEVICENAME "obdecho"
-#define OBD_ECHO_CLIENT_DEVICENAME "echo_client"
-
-#endif
+++ /dev/null
-#ifndef _OBD_EXT2
-#define _OBD_EXT2
-/*
- * Copyright (C) 2001 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-
-#define OBD_EXT2_RUNIT _IOWR('f', 61, long)
-
-#ifndef OBD_EXT2_DEVICENAME
-#define OBD_EXT2_DEVICENAME "obdext2"
-#endif
-
-/* development definitions */
-extern struct obdfs_sb_info *obd_sbi;
-extern struct file_operations *obd_fso;
-
-/* ext2_obd.c */
-extern struct obd_ops ext2_obd_ops;
-
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-
-/* super.c */
-#ifdef EXT2_OBD_DEBUG
-# undef ext2_debug
-# define ext2_debug(format, a...) CDEBUG(D_EXT2, format, ## a)
-# define ext2_error ext2_warning
-# define ext2_panic ext2_warning
-# define ext2_warning(sb, func, format, a...) CDEBUG(D_WARNING, format, ## a)
-#else
-# undef ext2_debug
-# define ext2_debug(format, a...) {}
-# define ext2_error(sb, func, format, a...) printk(KERN_ERR "%s: " format, func, ## a)
-# define ext2_panic(sb, func, format, a...) printk(KERN_CRIT "%s: " format, func, ## a)
-# define ext2_warning(sb, func, format, a...) printk(KERN_WARNING "%s: " format, func, ## a)
-#endif
-
-extern struct super_operations ext2_sops;
-int obd_remount (struct super_block * sb, int * flags, char * data);
-struct super_block * ext2_read_super (struct super_block * sb, void * data,
- int silent);
-/* punch.c */
-void ext2_truncate (struct inode * inode);
-int ext2_punch (struct inode * inode, loff_t start, size_t count);
-
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef _OBD_FILTER_H
-#define _OBD_FILTER_H
-
-#ifndef OBD_FILTER_DEVICENAME
-#define OBD_FILTER_DEVICENAME "obdfilter"
-#endif
-
-/* In-memory access to client data from OST struct */
-struct filter_export_data {
- struct list_head fed_open_head; /* files to close on disconnect */
- spinlock_t fed_lock; /* protects fed_open_head */
-};
-
-/* file data for open files on OST */
-struct filter_file_data {
- struct list_head ffd_export_list; /* export open list - fed_lock */
- struct file *ffd_file; /* file handle */
- __u64 ffd_servercookie; /* cookie for lustre handle */
-};
-
-struct filter_dentry_data {
- atomic_t fdd_open_count;
- int fdd_flags;
-};
-
-#define FILTER_FLAG_DESTROY 0x0001 /* destroy dentry on last file close */
-
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-
-#ifndef _OBD_LOV_H__
-#define _OBD_LOV_H__
-
-#ifdef __KERNEL__
-
-#define OBD_LOV_DEVICENAME "lov"
-
-void lov_unpackdesc(struct lov_desc *ld);
-void lov_packdesc(struct lov_desc *ld);
-
-static inline int lov_stripe_md_size(int stripes)
-{
- return sizeof(struct lov_stripe_md) + stripes*sizeof(struct lov_oinfo);
-}
-#endif
-
-static inline int lov_mds_md_size(int stripes)
-{
- return sizeof(struct lov_mds_md) + stripes*sizeof(struct lov_object_id);
-}
-
-#define IOC_LOV_TYPE 'g'
-#define IOC_LOV_MIN_NR 50
-#define IOC_LOV_SET_OSC_ACTIVE _IOWR('g', 50, long)
-#define IOC_LOV_MAX_NR 50
-
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Data structures for object storage targets and client: OST & OSC's
- *
- * See also lustre_idl.h for wire formats of requests.
- *
- */
-
-#ifndef _LUSTRE_OST_H
-#define _LUSTRE_OST_H
-
-#include <linux/obd_class.h>
-
-#define LUSTRE_OST_NAME "ost"
-#define LUSTRE_OSC_NAME "osc"
-
-/* ost/ost_pack.c */
-void ost_pack_niobuf(void **tmp, __u64 offset, __u32 len, __u32 flags,
- __u32 xid);
-void ost_unpack_niobuf(void **tmp, struct niobuf_remote **nbp);
-void ost_pack_ioo(void **tmp, struct lov_stripe_md *oa, int bufcnt);
-void ost_unpack_ioo(void **tmp, struct obd_ioobj **ioop);
-
-#endif
+++ /dev/null
-#ifndef _OBD_SNAP
-#define _OBD_SNAP
-/*
- * Copyright (C) 2001 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-
-#include <linux/obd_class.h>
-
-#define OBD_SNAP_MAGIC 0xfffffff3 /* an unlikely block number */
-
-#ifndef OBD_SNAP_DEVICENAME
-#define OBD_SNAP_DEVICENAME "obdsnap"
-#endif
-
-/* ioctls for manipulating snapshots 40 - 60 */
-#define OBD_SNAP_SETTABLE _IOWR('f', 40, long)
-#define OBD_SNAP_PRINTTABLE _IOWR('f', 41, long)
-#define OBD_SNAP_DELETE _IOWR('f', 42, long)
-#define OBD_SNAP_RESTORE _IOWR('f', 43, long)
-
-void snap_use(int table_no, int snap_index) ;
-void snap_unuse(int table_no, int snap_index) ;
-int snap_is_used(int table_no, int snap_index) ;
-int snap_table_attach(int tableno, int snap_index);
-
-#endif
+++ /dev/null
-#ifndef __OBD_SNAP_SUPP_H
-#define __OBD_SNAP_SUPP_H
-/*
- * Copyright (C) 2001 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-
-/* What we use to point to IDs in the obdmd data for snapshots. If we use
- * obd_id (8 bytes) instead of ino_t (4 bytes), we halve the number of
- * available snapshot slots (14 in 56 bytes vs. 7 in 56 bytes until we
- * increase the size of OBD_OBDMDSZ).
- */
-typedef obd_id snap_id;
-
-/* maximum number of snapshot tables we maintain in the kernel */
-#define SNAP_MAX_TABLES 8
-
-/* maximum number of snapshots per device
- must fit in "o_obdmd" area of struct obdo */
-#define SNAP_MAX ((OBD_OBDMDSZ - sizeof(uint32_t))/sizeof(snap_id))
-
-struct snap_md {
- uint32_t m_magic;
- snap_id m_ids[SNAP_MAX]; /* id of snaps; slot 0 has current id */
-};
-
-
-/* if time is 0 this designates the "current" snapshot, i.e.
- the head of the tree
-*/
-struct snap {
- time_t time;
- int index;
-};
-
-/* snap ioctl data for attach: current always in first slot of this array */
-struct snap_obd_data {
- int snap_dev; /* which device contains the data */
- unsigned int snap_index;/* which snapshot is ours */
- unsigned int snap_table;/* which table do we use */
-};
-
-
-/* snap ioctl data for table fiddling */
-struct snap_table_data {
- int tblcmd_no; /* which table */
- unsigned int tblcmd_count; /* how many snaps */
- struct snap tblcmd_snaps[SNAP_MAX]; /* sorted times! */
-};
-
-
-struct snap_table {
- spinlock_t tbl_lock;
- unsigned int tbl_count; /* how many snapshots exist in this table*/
- int tbl_used; /* bitmap of snaps in use by a device */
- time_t tbl_times[SNAP_MAX];
- int tbl_index[SNAP_MAX];
-};
-
-struct snap_iterdata {
- struct lustre_handle *conn;
- struct lustre_handle *ch_conn;
- int index;
- int previndex;
- int currentindex;
- int prevslot;
- time_t prevtime;
-};
-
-inline struct lustre_handle *child_conn(struct lustre_handle *conn);
-int snap_deleteobj(obd_id id, obd_gr group, void *data);
-int snap_restoreobj(obd_id id, obd_gr group, void *data);
-int snap_printobj(obd_id id, obd_gr group, void *data);
-int snap_iocontrol(unsigned int cmd, struct lustre_handle *conn, int len, void *karg, void *uarg);
-
-/* In the future, this function may have to deal with offsets into the obdmd.
- * Currently, we assume we have the whole obdmd struct.
- */
-static __inline__ struct snap_md *snap_obdmd(struct obdo *oa)
-{
- return ((struct snap_md *)(&oa->o_obdmd));
-}
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef _OBD_SUPPORT
-#define _OBD_SUPPORT
-
-#include <linux/config.h>
-#include <linux/autoconf.h>
-#include <linux/slab.h>
-#include <linux/highmem.h>
-#include <linux/kp30.h>
-
-/* global variables */
-extern unsigned long obd_memory;
-extern unsigned long obd_fail_loc;
-extern unsigned long obd_timeout;
-extern char obd_recovery_upcall[128];
-
-#define OBD_FAIL_MDS 0x100
-#define OBD_FAIL_MDS_HANDLE_UNPACK 0x101
-#define OBD_FAIL_MDS_GETATTR_NET 0x102
-#define OBD_FAIL_MDS_GETATTR_PACK 0x103
-#define OBD_FAIL_MDS_READPAGE_NET 0x104
-#define OBD_FAIL_MDS_READPAGE_PACK 0x105
-#define OBD_FAIL_MDS_SENDPAGE 0x106
-#define OBD_FAIL_MDS_REINT_NET 0x107
-#define OBD_FAIL_MDS_REINT_UNPACK 0x108
-#define OBD_FAIL_MDS_REINT_SETATTR 0x109
-#define OBD_FAIL_MDS_REINT_SETATTR_WRITE 0x10a
-#define OBD_FAIL_MDS_REINT_CREATE 0x10b
-#define OBD_FAIL_MDS_REINT_CREATE_WRITE 0x10c
-#define OBD_FAIL_MDS_REINT_UNLINK 0x10d
-#define OBD_FAIL_MDS_REINT_UNLINK_WRITE 0x10e
-#define OBD_FAIL_MDS_REINT_LINK 0x10f
-#define OBD_FAIL_MDS_REINT_LINK_WRITE 0x110
-#define OBD_FAIL_MDS_REINT_RENAME 0x111
-#define OBD_FAIL_MDS_REINT_RENAME_WRITE 0x112
-#define OBD_FAIL_MDS_OPEN_NET 0x113
-#define OBD_FAIL_MDS_OPEN_PACK 0x114
-#define OBD_FAIL_MDS_CLOSE_NET 0x115
-#define OBD_FAIL_MDS_CLOSE_PACK 0x116
-#define OBD_FAIL_MDS_CONNECT_NET 0x117
-#define OBD_FAIL_MDS_CONNECT_PACK 0x118
-#define OBD_FAIL_MDS_REINT_NET_REP 0x119
-#define OBD_FAIL_MDS_DISCONNECT_NET 0x11a
-#define OBD_FAIL_MDS_GETSTATUS_NET 0x11b
-#define OBD_FAIL_MDS_GETSTATUS_PACK 0x11c
-#define OBD_FAIL_MDS_STATFS_PACK 0x11d
-#define OBD_FAIL_MDS_STATFS_NET 0x11e
-
-#define OBD_FAIL_OST 0x200
-#define OBD_FAIL_OST_CONNECT_NET 0x201
-#define OBD_FAIL_OST_DISCONNECT_NET 0x202
-#define OBD_FAIL_OST_GET_INFO_NET 0x203
-#define OBD_FAIL_OST_CREATE_NET 0x204
-#define OBD_FAIL_OST_DESTROY_NET 0x205
-#define OBD_FAIL_OST_GETATTR_NET 0x206
-#define OBD_FAIL_OST_SETATTR_NET 0x207
-#define OBD_FAIL_OST_OPEN_NET 0x208
-#define OBD_FAIL_OST_CLOSE_NET 0x209
-#define OBD_FAIL_OST_BRW_NET 0x20a
-#define OBD_FAIL_OST_PUNCH_NET 0x20b
-#define OBD_FAIL_OST_STATFS_NET 0x20c
-#define OBD_FAIL_OST_HANDLE_UNPACK 0x20d
-#define OBD_FAIL_OST_BRW_WRITE_BULK 0x20e
-#define OBD_FAIL_OST_BRW_READ_BULK 0x20f
-
-#define OBD_FAIL_LDLM 0x300
-#define OBD_FAIL_LDLM_NAMESPACE_NEW 0x301
-#define OBD_FAIL_LDLM_ENQUEUE 0x302
-#define OBD_FAIL_LDLM_CONVERT 0x303
-#define OBD_FAIL_LDLM_CANCEL 0x304
-#define OBD_FAIL_LDLM_BL_CALLBACK 0x305
-#define OBD_FAIL_LDLM_CP_CALLBACK 0x306
-
-#define OBD_FAIL_OSC 0x400
-#define OBD_FAIL_OSC_BRW_READ_BULK 0x401
-#define OBD_FAIL_OSC_BRW_WRITE_BULK 0x402
-#define OBD_FAIL_OSC_LOCK_BL_AST 0x403
-#define OBD_FAIL_OSC_LOCK_CP_AST 0x404
-
-/* preparation for a more advanced failure testbed (not functional yet) */
-#define OBD_FAIL_MASK_SYS 0x0000FF00
-#define OBD_FAIL_MASK_LOC (0x000000FF | OBD_FAIL_MASK_SYS)
-#define OBD_FAIL_ONCE 0x80000000
-#define OBD_FAILED 0x40000000
-#define OBD_FAIL_MDS_ALL_NET 0x01000000
-#define OBD_FAIL_OST_ALL_NET 0x02000000
-
-#define OBD_FAIL_CHECK(id) ((obd_fail_loc & OBD_FAIL_MASK_LOC) == (id) && \
- ((obd_fail_loc & (OBD_FAILED | OBD_FAIL_ONCE))!=\
- (OBD_FAILED | OBD_FAIL_ONCE)))
-
-#define OBD_FAIL_RETURN(id, ret) \
-do { \
- if (OBD_FAIL_CHECK(id)) { \
- CERROR("obd_fail_loc=%x, fail operation rc=%d\n", id, ret); \
- obd_fail_loc |= OBD_FAILED; \
- if ((id) & OBD_FAIL_ONCE) \
- obd_fail_loc |= OBD_FAIL_ONCE; \
- RETURN(ret); \
- } \
-} while(0)
-
-#include <linux/types.h>
-#include <linux/blkdev.h>
-
-#define fixme() CDEBUG(D_OTHER, "FIXME\n");
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
-#define ll_bdevname(a) __bdevname((a))
-#define ll_lock_kernel lock_kernel()
-#else
-#define ll_lock_kernel
-#define ll_bdevname(a) bdevname((a))
-#endif
-
-static inline void OBD_FAIL_WRITE(int id, kdev_t dev)
-{
- if (OBD_FAIL_CHECK(id)) {
-#ifdef CONFIG_DEV_RDONLY
- CERROR("obd_fail_loc=%x, fail write operation on %s\n",
- id, ll_bdevname(dev));
- dev_set_rdonly(dev, 2);
-#else
- CERROR("obd_fail_loc=%x, can't fail write operation on %s\n",
- id, ll_bdevname(dev));
-#endif
- /* We set FAIL_ONCE because we never "un-fail" a device */
- obd_fail_loc |= OBD_FAILED | OBD_FAIL_ONCE;
- }
-}
-
-#define OBD_ALLOC(ptr, size) \
-do { \
- void *lptr; \
- long s = (size); \
- (ptr) = lptr = kmalloc(s, GFP_KERNEL); \
- if (lptr == NULL) { \
- CERROR("kmalloc of '" #ptr "' (%ld bytes) failed " \
- "at %s:%d\n", s, __FILE__, __LINE__); \
- } else { \
- memset(lptr, 0, s); \
- obd_memory += s; \
- CDEBUG(D_MALLOC, "kmalloced '" #ptr "': %ld at " \
- "%p (tot %ld).\n", s, lptr, obd_memory); \
- } \
-} while (0)
-
-#ifdef CONFIG_DEBUG_SLAB
-#define POISON(lptr, s) do {} while (0)
-#else
-#define POISON(lptr, s) memset(lptr, 0xb6, s)
-#endif
-
-#define OBD_FREE(ptr, size) \
-do { \
- void *lptr = (ptr); \
- int s = (size); \
- LASSERT(lptr); \
- POISON(lptr, s); \
- kfree(lptr); \
- obd_memory -= s; \
- CDEBUG(D_MALLOC, "kfreed '" #ptr "': %d at %p (tot %ld).\n", \
- s, lptr, obd_memory); \
- (ptr) = (void *)0xdeadbeef; \
-} while (0)
-
-#ifdef CONFIG_HIGHMEM
-extern void obd_kmap_get(int count, int server);
-extern void obd_kmap_put(int count);
-#else
-#define obd_kmap_get(count, server) do {} while (0)
-#define obd_kmap_put(count) do {} while (0)
-#endif
-#endif
+++ /dev/null
-/*
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * obdtrace (header file) - is useful for tracing and performance
- * debug of the Lustre obd protocol stack. obdtrace is a transparent
- * logical obd driver that prints commands their in- and outbound
- * parameters. obdtrace maintains statistics about number and latency
- * of the obd commands that pass through it. As such it is also use
- * for performance analysis.
- *
- * Copyright (c) 2001 Rumi Zahir <rumi.zahir@intel.com>
- */
-
-#ifndef __OBD_TRACE_H
-#define __OBD_TRACE_H
-
-#include <class/obd_class.h>
-
-#endif
+++ /dev/null
-#!/bin/sh
-#
-# install - install a program, script, or datafile
-# This comes from X11R5 (mit/util/scripts/install.sh).
-#
-# Copyright 1991 by the Massachusetts Institute of Technology
-#
-# Permission to use, copy, modify, distribute, and sell this software and its
-# documentation for any purpose is hereby granted without fee, provided that
-# the above copyright notice appear in all copies and that both that
-# copyright notice and this permission notice appear in supporting
-# documentation, and that the name of M.I.T. not be used in advertising or
-# publicity pertaining to distribution of the software without specific,
-# written prior permission. M.I.T. makes no representations about the
-# suitability of this software for any purpose. It is provided "as is"
-# without express or implied warranty.
-#
-# 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=""
-
-while [ x"$1" != x ]; do
- case $1 in
- -c) instcmd="$cpprog"
- shift
- continue;;
-
- -d) dir_arg=true
- shift
- continue;;
-
- -m) chmodcmd="$chmodprog $2"
- shift
- shift
- continue;;
-
- -o) chowncmd="$chownprog $2"
- shift
- shift
- continue;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift
- shift
- continue;;
-
- -s) stripcmd="$stripprog"
- shift
- continue;;
-
- -t=*) transformarg=`echo $1 | sed 's/-t=//'`
- shift
- continue;;
-
- -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
- shift
- continue;;
-
- *) if [ x"$src" = x ]
- then
- src=$1
- else
- # this colon is to work around a 386BSD /bin/sh bug
- :
- dst=$1
- fi
- shift
- continue;;
- esac
-done
-
-if [ x"$src" = x ]
-then
- echo "install: no input file specified"
- exit 1
-else
- true
-fi
-
-if [ x"$dir_arg" != x ]; then
- dst=$src
- src=""
-
- if [ -d $dst ]; then
- instcmd=:
- chmodcmd=""
- else
- instcmd=mkdir
- 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 [ -f $src -o -d $src ]
- then
- true
- else
- echo "install: $src does not exist"
- exit 1
- fi
-
- if [ x"$dst" = x ]
- then
- echo "install: no destination specified"
- exit 1
- else
- true
- fi
-
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
-
- if [ -d $dst ]
- then
- dst="$dst"/`basename $src`
- else
- true
- fi
-fi
-
-## this sed command emulates the dirname command
-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
-
-# Make sure that the destination directory exists.
-# this part is taken from Noah Friedman's mkinstalldirs script
-
-# Skip lots of stat calls in the usual case.
-if [ ! -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 [ $# -ne 0 ] ; do
- pathcomp="${pathcomp}${1}"
- shift
-
- if [ ! -d "${pathcomp}" ] ;
- then
- $mkdirprog "${pathcomp}"
- else
- true
- fi
-
- pathcomp="${pathcomp}/"
-done
-fi
-
-if [ x"$dir_arg" != x ]
-then
- $doit $instcmd $dst &&
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
-else
-
-# If we're going to rename the final executable, determine the name now.
-
- if [ x"$transformarg" = x ]
- then
- dstfile=`basename $dst`
- else
- dstfile=`basename $dst $transformbasename |
- sed $transformarg`$transformbasename
- fi
-
-# don't allow the sed command to completely eliminate the filename
-
- if [ x"$dstfile" = x ]
- then
- dstfile=`basename $dst`
- else
- true
- fi
-
-# Make a temp file name in the proper directory.
-
- dsttmp=$dstdir/#inst.$$#
-
-# Move or copy the file name to the temp name
-
- $doit $instcmd $src $dsttmp &&
-
- trap "rm -f ${dsttmp}" 0 &&
-
-# 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.
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
-
-# Now rename the file to the real destination.
-
- $doit $rmcmd -f $dstdir/$dstfile &&
- $doit $mvcmd $dsttmp $dstdir/$dstfile
-
-fi &&
-
-
-exit 0
+++ /dev/null
-.deps
-Makefile
-Makefile.in
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=
-MODULE = ldlm
-modulefs_DATA = ldlm.o
-EXTRA_PROGRAMS = ldlm
-
-ldlm_SOURCES = l_lock.c ldlm_lock.c ldlm_resource.c ldlm_test.c ldlm_lockd.c \
-ldlm_extent.c ldlm_request.c
-
-include $(top_srcdir)/Rules
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.sf.net/projects/lustre/
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/version.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
-#include <asm/segment.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/smp_lock.h>
-
-#define DEBUG_SUBSYSTEM S_LDLM
-
-#include <linux/obd_class.h>
-#include <linux/lustre_lib.h>
-
-/* invariants:
- - only the owner of the lock changes l_owner/l_depth
- - if a non-owner changes or checks the variables a spin lock is taken
-*/
-
-void l_lock_init(struct lustre_lock *lock)
-{
- sema_init(&lock->l_sem, 1);
- spin_lock_init(&lock->l_spin);
-}
-
-void l_lock(struct lustre_lock *lock)
-{
- int owner = 0;
-
- spin_lock(&lock->l_spin);
- if (lock->l_owner == current)
- owner = 1;
- spin_unlock(&lock->l_spin);
-
- if (owner) {
- ++lock->l_depth;
- } else {
- down(&lock->l_sem);
- spin_lock(&lock->l_spin);
- lock->l_owner = current;
- lock->l_depth = 0;
- spin_unlock(&lock->l_spin);
- }
-}
-
-void l_unlock(struct lustre_lock *lock)
-{
- LASSERT(lock->l_owner == current);
- LASSERT(lock->l_depth >= 0);
-
- spin_lock(&lock->l_spin);
- if (--lock->l_depth < 0) {
- lock->l_owner = NULL;
- spin_unlock(&lock->l_spin);
- up(&lock->l_sem);
- return;
- }
- spin_unlock(&lock->l_spin);
-}
-
-int l_has_lock(struct lustre_lock *lock)
-{
- int depth = -1, owner = 0;
-
- spin_lock(&lock->l_spin);
- if (lock->l_owner == current) {
- depth = lock->l_depth;
- owner = 1;
- }
- spin_unlock(&lock->l_spin);
-
- if (depth >= 0)
- CDEBUG(D_INFO, "lock_depth: %d\n", depth);
- return owner;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * by Cluster File Systems, Inc.
- * authors, Peter Braam <braam@clusterfs.com> &
- * Phil Schwan <phil@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LDLM
-
-#include <linux/lustre_dlm.h>
-
-/* This function will be called to judge if the granted queue of another child
- * (read: another extent) is conflicting and needs its granted queue walked to
- * issue callbacks.
- *
- * This helps to find conflicts between read and write locks on overlapping
- * extents. */
-int ldlm_extent_compat(struct ldlm_lock *a, struct ldlm_lock *b)
-{
- if (MAX(a->l_extent.start, b->l_extent.start) <=
- MIN(a->l_extent.end, b->l_extent.end))
- RETURN(0);
-
- RETURN(1);
-}
-
-/* The purpose of this function is to return:
- * - the maximum extent
- * - containing the requested extent
- * - and not overlapping existing extents outside the requested one
- *
- * An alternative policy is to not shrink the new extent when conflicts exist.
- *
- * To reconstruct our formulas, take a deep breath. */
-static void policy_internal(struct list_head *queue, struct ldlm_extent *req_ex,
- struct ldlm_extent *new_ex, ldlm_mode_t mode)
-{
- struct list_head *tmp;
-
- list_for_each(tmp, queue) {
- struct ldlm_lock *lock;
- lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-
- if (lock->l_extent.end < req_ex->start)
- new_ex->start = MIN(lock->l_extent.end, new_ex->start);
- else {
- if (lock->l_extent.start < req_ex->start &&
- !lockmode_compat(lock->l_req_mode, mode))
- /* Policy: minimize conflict overlap */
- new_ex->start = req_ex->start;
- }
- if (lock->l_extent.start > req_ex->end)
- new_ex->end = MAX(lock->l_extent.start, new_ex->end);
- else {
- if (lock->l_extent.end > req_ex->end &&
- !lockmode_compat(lock->l_req_mode, mode))
- /* Policy: minimize conflict overlap */
- new_ex->end = req_ex->end;
- }
- }
-}
-
-/* apply the internal policy by walking all the lists */
-int ldlm_extent_policy(struct ldlm_lock *lock, void *req_cookie,
- ldlm_mode_t mode, int flags, void *data)
-{
- struct ldlm_resource *res = lock->l_resource;
- struct ldlm_extent *req_ex = req_cookie;
- struct ldlm_extent new_ex;
- new_ex.start = 0;
- new_ex.end = ~0;
-
- if (!res)
- LBUG();
-
- l_lock(&res->lr_namespace->ns_lock);
- policy_internal(&res->lr_granted, req_ex, &new_ex, mode);
- policy_internal(&res->lr_converting, req_ex, &new_ex, mode);
- policy_internal(&res->lr_waiting, req_ex, &new_ex, mode);
- l_unlock(&res->lr_namespace->ns_lock);
-
- memcpy(&lock->l_extent, &new_ex, sizeof(new_ex));
-
- LDLM_DEBUG(lock, "new extent "LPU64" -> "LPU64, new_ex.start,
- new_ex.end);
-
- if (new_ex.end != req_ex->end || new_ex.start != req_ex->start)
- return ELDLM_LOCK_CHANGED;
- else
- return 0;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002 Cluster File Systems, Inc.
- * Author: Peter Braam <braam@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_LDLM
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/random.h>
-#include <linux/lustre_dlm.h>
-#include <linux/lustre_mds.h>
-#include <linux/obd_class.h>
-
-//struct lustre_lock ldlm_everything_lock;
-
-/* lock types */
-char *ldlm_lockname[] = {
- [0] "--",
- [LCK_EX] "EX",
- [LCK_PW] "PW",
- [LCK_PR] "PR",
- [LCK_CW] "CW",
- [LCK_CR] "CR",
- [LCK_NL] "NL"
-};
-char *ldlm_typename[] = {
- [LDLM_PLAIN] "PLN",
- [LDLM_EXTENT] "EXT",
-};
-
-char *ldlm_it2str(int it)
-{
- switch (it) {
- case IT_OPEN:
- return "open";
- case IT_CREAT:
- return "creat";
- case (IT_OPEN | IT_CREAT):
- return "open|creat";
- case IT_MKDIR:
- return "mkdir";
- case IT_LINK:
- return "link";
- case IT_LINK2:
- return "link2";
- case IT_SYMLINK:
- return "symlink";
- case IT_UNLINK:
- return "unlink";
- case IT_RMDIR:
- return "rmdir";
- case IT_RENAME:
- return "rename";
- case IT_RENAME2:
- return "rename2";
- case IT_READDIR:
- return "readdir";
- case IT_GETATTR:
- return "getattr";
- case IT_SETATTR:
- return "setattr";
- case IT_READLINK:
- return "readlink";
- case IT_MKNOD:
- return "mknod";
- case IT_LOOKUP:
- return "lookup";
- default:
- CERROR("Unknown intent %d\n", it);
- return "UNKNOWN";
- }
-}
-
-extern kmem_cache_t *ldlm_lock_slab;
-struct lustre_lock ldlm_handle_lock;
-
-static int ldlm_plain_compat(struct ldlm_lock *a, struct ldlm_lock *b);
-
-ldlm_res_compat ldlm_res_compat_table[] = {
- [LDLM_PLAIN] ldlm_plain_compat,
- [LDLM_EXTENT] ldlm_extent_compat,
-};
-
-static ldlm_res_policy ldlm_intent_policy_func;
-
-static int ldlm_plain_policy(struct ldlm_lock *lock, void *req_cookie,
- ldlm_mode_t mode, int flags, void *data)
-{
- if ((flags & LDLM_FL_HAS_INTENT) && ldlm_intent_policy_func) {
- return ldlm_intent_policy_func(lock, req_cookie, mode, flags,
- data);
- }
-
- return ELDLM_OK;
-}
-
-ldlm_res_policy ldlm_res_policy_table[] = {
- [LDLM_PLAIN] ldlm_plain_policy,
- [LDLM_EXTENT] ldlm_extent_policy,
-};
-
-void ldlm_register_intent(ldlm_res_policy arg)
-{
- ldlm_intent_policy_func = arg;
-}
-
-void ldlm_unregister_intent(void)
-{
- ldlm_intent_policy_func = NULL;
-}
-
-/*
- * REFCOUNTED LOCK OBJECTS
- */
-
-
-/*
- * Lock refcounts, during creation:
- * - one special one for allocation, dec'd only once in destroy
- * - one for being a lock that's in-use
- * - one for the addref associated with a new lock
- */
-struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock)
-{
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- atomic_inc(&lock->l_refc);
- ldlm_resource_getref(lock->l_resource);
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- return lock;
-}
-
-void ldlm_lock_put(struct ldlm_lock *lock)
-{
- struct ldlm_namespace *ns = lock->l_resource->lr_namespace;
- ENTRY;
-
- l_lock(&ns->ns_lock);
- atomic_dec(&lock->l_refc);
- LASSERT(atomic_read(&lock->l_refc) >= 0);
-
- if (ldlm_resource_putref(lock->l_resource)) {
- LASSERT(atomic_read(&lock->l_refc) == 0);
- lock->l_resource = NULL;
- }
- if (lock->l_parent)
- LDLM_LOCK_PUT(lock->l_parent);
-
- if (atomic_read(&lock->l_refc) == 0) {
- LASSERT(lock->l_destroyed);
- l_unlock(&ns->ns_lock);
- LDLM_DEBUG(lock, "final lock_put on destroyed lock, freeing");
-
- spin_lock(&ns->ns_counter_lock);
- ns->ns_locks--;
- spin_unlock(&ns->ns_counter_lock);
-
- lock->l_resource = NULL;
- lock->l_random = DEAD_HANDLE_MAGIC;
- if (lock->l_export && lock->l_export->exp_connection)
- ptlrpc_put_connection(lock->l_export->exp_connection);
- memset(lock, 0x5a, sizeof(*lock));
- kmem_cache_free(ldlm_lock_slab, lock);
- CDEBUG(D_MALLOC, "kfreed 'lock': %d at %p (tot 0).\n",
- sizeof(*lock), lock);
- } else
- l_unlock(&ns->ns_lock);
-
- EXIT;
-}
-
-void ldlm_lock_remove_from_lru(struct ldlm_lock *lock)
-{
- ENTRY;
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- if (!list_empty(&lock->l_lru)) {
- list_del_init(&lock->l_lru);
- lock->l_resource->lr_namespace->ns_nr_unused--;
- LASSERT(lock->l_resource->lr_namespace->ns_nr_unused >= 0);
- }
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- EXIT;
-}
-
-void ldlm_lock_destroy(struct ldlm_lock *lock)
-{
- ENTRY;
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
-
- if (!list_empty(&lock->l_children)) {
- LDLM_DEBUG(lock, "still has children (%p)!",
- lock->l_children.next);
- ldlm_lock_dump(lock);
- LBUG();
- }
- if (lock->l_readers || lock->l_writers) {
- LDLM_DEBUG(lock, "lock still has references");
- ldlm_lock_dump(lock);
- }
-
- if (!list_empty(&lock->l_res_link)) {
- ldlm_lock_dump(lock);
- LBUG();
- }
-
- if (lock->l_destroyed) {
- LASSERT(list_empty(&lock->l_lru));
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- EXIT;
- return;
- }
- lock->l_destroyed = 1;
-
- list_del(&lock->l_export_chain);
- lock->l_export = NULL;
- ldlm_lock_remove_from_lru(lock);
-
- /* Wake anyone waiting for this lock */
- /* FIXME: I should probably add yet another flag, instead of using
- * l_export to only call this on clients */
- if (lock->l_export && lock->l_completion_ast)
- lock->l_completion_ast(lock, 0);
-
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- LDLM_LOCK_PUT(lock);
- EXIT;
-}
-
-/*
- usage: pass in a resource on which you have done get
- pass in a parent lock on which you have done a get
- do not put the resource or the parent
- returns: lock with refcount 1
-*/
-static struct ldlm_lock *ldlm_lock_new(struct ldlm_lock *parent,
- struct ldlm_resource *resource)
-{
- struct ldlm_lock *lock;
- ENTRY;
-
- if (resource == NULL)
- LBUG();
-
- lock = kmem_cache_alloc(ldlm_lock_slab, SLAB_KERNEL);
- if (lock == NULL)
- RETURN(NULL);
-
- memset(lock, 0, sizeof(*lock));
- get_random_bytes(&lock->l_random, sizeof(__u64));
-
- lock->l_resource = resource;
- /* this refcount matches the one of the resource passed
- in which is not being put away */
- atomic_set(&lock->l_refc, 1);
- INIT_LIST_HEAD(&lock->l_children);
- INIT_LIST_HEAD(&lock->l_res_link);
- INIT_LIST_HEAD(&lock->l_lru);
- INIT_LIST_HEAD(&lock->l_export_chain);
- INIT_LIST_HEAD(&lock->l_pending_chain);
- init_waitqueue_head(&lock->l_waitq);
-
- spin_lock(&resource->lr_namespace->ns_counter_lock);
- resource->lr_namespace->ns_locks++;
- spin_unlock(&resource->lr_namespace->ns_counter_lock);
-
- if (parent != NULL) {
- l_lock(&parent->l_resource->lr_namespace->ns_lock);
- lock->l_parent = parent;
- list_add(&lock->l_childof, &parent->l_children);
- l_unlock(&parent->l_resource->lr_namespace->ns_lock);
- }
-
- CDEBUG(D_MALLOC, "kmalloced 'lock': %d at "
- "%p (tot %d).\n", sizeof(*lock), lock, 1);
- /* this is the extra refcount, to prevent the lock from evaporating */
- LDLM_LOCK_GET(lock);
- RETURN(lock);
-}
-
-int ldlm_lock_change_resource(struct ldlm_lock *lock, __u64 new_resid[3])
-{
- struct ldlm_namespace *ns = lock->l_resource->lr_namespace;
- struct ldlm_resource *oldres = lock->l_resource;
- int i, refc;
- ENTRY;
-
- l_lock(&ns->ns_lock);
- if (memcmp(new_resid, lock->l_resource->lr_name,
- sizeof(lock->l_resource->lr_name)) == 0) {
- /* Nothing to do */
- l_unlock(&ns->ns_lock);
- RETURN(0);
- }
-
- LASSERT(new_resid[0] != 0);
-
- /* This function assumes that the lock isn't on any lists */
- LASSERT(list_empty(&lock->l_res_link));
-
- lock->l_resource = ldlm_resource_get(ns, NULL, new_resid,
- lock->l_resource->lr_type, 1);
- if (lock->l_resource == NULL) {
- LBUG();
- RETURN(-ENOMEM);
- }
-
- /* move references over */
- refc = atomic_read(&lock->l_refc);
- for (i = 0; i < refc; i++) {
- int rc;
- ldlm_resource_getref(lock->l_resource);
- rc = ldlm_resource_putref(oldres);
- if (rc == 1 && i != refc - 1)
- LBUG();
- }
- /* compensate for the initial get above.. */
- ldlm_resource_putref(lock->l_resource);
-
- l_unlock(&ns->ns_lock);
- RETURN(0);
-}
-
-/*
- * HANDLES
- */
-
-void ldlm_lock2handle(struct ldlm_lock *lock, struct lustre_handle *lockh)
-{
- lockh->addr = (__u64) (unsigned long)lock;
- lockh->cookie = lock->l_random;
-}
-
-/*
- * if flags: atomically get the lock and set the flags.
- * Return NULL if flag already set
- */
-
-struct ldlm_lock *__ldlm_handle2lock(struct lustre_handle *handle, int strict,
- int flags)
-{
- struct ldlm_lock *lock = NULL, *retval = NULL;
- ENTRY;
-
- LASSERT(handle);
-
- if (!handle->addr)
- RETURN(NULL);
-
- lock = (struct ldlm_lock *)(unsigned long)(handle->addr);
- if (!kmem_cache_validate(ldlm_lock_slab, (void *)lock)) {
- //CERROR("bogus lock %p\n", lock);
- GOTO(out2, retval);
- }
-
- if (lock->l_random != handle->cookie) {
- //CERROR("bogus cookie: lock %p has "LPX64" vs. handle "LPX64
- // "\n", lock, lock->l_random, handle->cookie);
- GOTO(out2, NULL);
- }
- if (!lock->l_resource) {
- CERROR("trying to lock bogus resource: lock %p\n", lock);
- //LDLM_DEBUG(lock, "ldlm_handle2lock(%p)", lock);
- GOTO(out2, retval);
- }
- if (!lock->l_resource->lr_namespace) {
- CERROR("trying to lock bogus namespace: lock %p\n", lock);
- //LDLM_DEBUG(lock, "ldlm_handle2lock(%p)", lock);
- GOTO(out2, retval);
- }
-
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- if (strict && lock->l_destroyed) {
- CERROR("lock already destroyed: lock %p\n", lock);
- //LDLM_DEBUG(lock, "ldlm_handle2lock(%p)", lock);
- GOTO(out, NULL);
- }
-
- if (flags && (lock->l_flags & flags))
- GOTO(out, NULL);
-
- if (flags)
- lock->l_flags |= flags;
-
- retval = LDLM_LOCK_GET(lock);
- if (!retval)
- CERROR("lock disappeared below us!!! %p\n", lock);
- EXIT;
- out:
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- out2:
- return retval;
-}
-
-static int ldlm_plain_compat(struct ldlm_lock *a, struct ldlm_lock *b)
-{
- return lockmode_compat(a->l_req_mode, b->l_req_mode);
-}
-
-void ldlm_lock2desc(struct ldlm_lock *lock, struct ldlm_lock_desc *desc)
-{
- ldlm_res2desc(lock->l_resource, &desc->l_resource);
- desc->l_req_mode = lock->l_req_mode;
- desc->l_granted_mode = lock->l_granted_mode;
- memcpy(&desc->l_extent, &lock->l_extent, sizeof(desc->l_extent));
- memcpy(desc->l_version, lock->l_version, sizeof(desc->l_version));
-}
-
-static void ldlm_add_ast_work_item(struct ldlm_lock *lock,
- struct ldlm_lock *new)
-{
- struct ldlm_ast_work *w;
- ENTRY;
-
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- if (new && (lock->l_flags & LDLM_FL_AST_SENT))
- GOTO(out, 0);
-
- OBD_ALLOC(w, sizeof(*w));
- if (!w) {
- LBUG();
- GOTO(out, 0);
- }
-
- if (new) {
- lock->l_flags |= LDLM_FL_AST_SENT;
- w->w_blocking = 1;
- ldlm_lock2desc(new, &w->w_desc);
- }
-
- w->w_lock = LDLM_LOCK_GET(lock);
- list_add(&w->w_list, lock->l_resource->lr_tmp);
- out:
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- return;
-}
-
-void ldlm_lock_addref(struct lustre_handle *lockh, __u32 mode)
-{
- struct ldlm_lock *lock;
-
- lock = ldlm_handle2lock(lockh);
- ldlm_lock_addref_internal(lock, mode);
- LDLM_LOCK_PUT(lock);
-}
-
-/* only called for local locks */
-void ldlm_lock_addref_internal(struct ldlm_lock *lock, __u32 mode)
-{
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- ldlm_lock_remove_from_lru(lock);
- if (mode == LCK_NL || mode == LCK_CR || mode == LCK_PR)
- lock->l_readers++;
- else
- lock->l_writers++;
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- LDLM_LOCK_GET(lock);
- LDLM_DEBUG(lock, "ldlm_lock_addref(%s)", ldlm_lockname[mode]);
-}
-
-/* Args: unlocked lock */
-int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns,
- __u64 *res_id, int flags);
-
-void ldlm_lock_decref(struct lustre_handle *lockh, __u32 mode)
-{
- struct ldlm_lock *lock = __ldlm_handle2lock(lockh, 0, 0);
- struct ldlm_namespace *ns;
- ENTRY;
-
- if (lock == NULL)
- LBUG();
-
- LDLM_DEBUG(lock, "ldlm_lock_decref(%s)", ldlm_lockname[mode]);
- ns = lock->l_resource->lr_namespace;
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- if (mode == LCK_NL || mode == LCK_CR || mode == LCK_PR)
- lock->l_readers--;
- else
- lock->l_writers--;
-
- /* If we received a blocked AST and this was the last reference,
- * run the callback. */
- if (!lock->l_readers && !lock->l_writers &&
- (lock->l_flags & LDLM_FL_CBPENDING)) {
- if (!lock->l_resource->lr_namespace->ns_client &&
- lock->l_export)
- CERROR("FL_CBPENDING set on non-local lock--just a "
- "warning\n");
-
- LDLM_DEBUG(lock, "final decref done on cbpending lock");
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
-
- /* FIXME: need a real 'desc' here */
- lock->l_blocking_ast(lock, NULL, lock->l_data,
- lock->l_data_len, LDLM_CB_BLOCKING);
- } else if (ns->ns_client && !lock->l_readers && !lock->l_writers) {
- LASSERT(list_empty(&lock->l_lru));
- LASSERT(ns->ns_nr_unused >= 0);
- list_add_tail(&lock->l_lru, &ns->ns_unused_list);
- ns->ns_nr_unused++;
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- ldlm_cancel_lru(ns);
- } else
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
-
- LDLM_LOCK_PUT(lock); /* matches the ldlm_lock_get in addref */
- LDLM_LOCK_PUT(lock); /* matches the handle2lock above */
-
- EXIT;
-}
-
-static int ldlm_lock_compat_list(struct ldlm_lock *lock, int send_cbs,
- struct list_head *queue)
-{
- struct list_head *tmp, *pos;
- int rc = 1;
-
- list_for_each_safe(tmp, pos, queue) {
- struct ldlm_lock *child;
- ldlm_res_compat compat;
-
- child = list_entry(tmp, struct ldlm_lock, l_res_link);
- if (lock == child)
- continue;
-
- compat = ldlm_res_compat_table[child->l_resource->lr_type];
- if (compat && compat(child, lock)) {
- CDEBUG(D_OTHER, "compat function succeded, next.\n");
- continue;
- }
- if (lockmode_compat(child->l_granted_mode, lock->l_req_mode)) {
- CDEBUG(D_OTHER, "lock modes are compatible, next.\n");
- continue;
- }
-
- rc = 0;
-
- if (send_cbs && child->l_blocking_ast != NULL) {
- CDEBUG(D_OTHER, "lock %p incompatible; sending "
- "blocking AST.\n", child);
- ldlm_add_ast_work_item(child, lock);
- }
- }
-
- return rc;
-}
-
-static int ldlm_lock_compat(struct ldlm_lock *lock, int send_cbs)
-{
- int rc;
- ENTRY;
-
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- rc = ldlm_lock_compat_list(lock, send_cbs,
- &lock->l_resource->lr_granted);
- /* FIXME: should we be sending ASTs to converting? */
- if (rc)
- rc = ldlm_lock_compat_list
- (lock, send_cbs, &lock->l_resource->lr_converting);
-
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- RETURN(rc);
-}
-
-/* NOTE: called by
- - ldlm_handle_enqueuque - resource
-*/
-void ldlm_grant_lock(struct ldlm_lock *lock)
-{
- struct ldlm_resource *res = lock->l_resource;
- ENTRY;
-
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- ldlm_resource_add_lock(res, &res->lr_granted, lock);
- lock->l_granted_mode = lock->l_req_mode;
-
- if (lock->l_granted_mode < res->lr_most_restr)
- res->lr_most_restr = lock->l_granted_mode;
-
- if (lock->l_completion_ast) {
- ldlm_add_ast_work_item(lock, NULL);
- }
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- EXIT;
-}
-
-/* returns a referenced lock or NULL */
-static struct ldlm_lock *search_queue(struct list_head *queue, ldlm_mode_t mode,
- struct ldlm_extent *extent,
- struct ldlm_lock *old_lock)
-{
- struct ldlm_lock *lock;
- struct list_head *tmp;
-
- list_for_each(tmp, queue) {
- lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-
- if (lock == old_lock)
- continue;
-
- if (lock->l_flags & LDLM_FL_CBPENDING)
- continue;
-
- if (lock->l_req_mode != mode)
- continue;
-
- if (lock->l_resource->lr_type == LDLM_EXTENT &&
- (lock->l_extent.start > extent->start ||
- lock->l_extent.end < extent->end))
- continue;
-
- if (lock->l_destroyed)
- continue;
-
- ldlm_lock_addref_internal(lock, mode);
- return lock;
- }
-
- return NULL;
-}
-
-/* Can be called in two ways:
- *
- * If 'ns' is NULL, then lockh describes an existing lock that we want to look
- * for a duplicate of.
- *
- * Otherwise, all of the fields must be filled in, to match against.
- *
- * Returns 1 if it finds an already-existing lock that is compatible; in this
- * case, lockh is filled in with a addref()ed lock
- */
-int ldlm_lock_match(struct ldlm_namespace *ns, __u64 *res_id, __u32 type,
- void *cookie, int cookielen, ldlm_mode_t mode,
- struct lustre_handle *lockh)
-{
- struct ldlm_resource *res;
- struct ldlm_lock *lock, *old_lock = NULL;
- int rc = 0;
- ENTRY;
-
- if (ns == NULL) {
- old_lock = ldlm_handle2lock(lockh);
- LASSERT(old_lock);
-
- ns = old_lock->l_resource->lr_namespace;
- res_id = old_lock->l_resource->lr_name;
- type = old_lock->l_resource->lr_type;
- mode = old_lock->l_req_mode;
- }
-
- res = ldlm_resource_get(ns, NULL, res_id, type, 0);
- if (res == NULL) {
- LASSERT(old_lock == NULL);
- RETURN(0);
- }
-
- l_lock(&ns->ns_lock);
-
- if ((lock = search_queue(&res->lr_granted, mode, cookie, old_lock)))
- GOTO(out, rc = 1);
- if ((lock = search_queue(&res->lr_converting, mode, cookie, old_lock)))
- GOTO(out, rc = 1);
- if ((lock = search_queue(&res->lr_waiting, mode, cookie, old_lock)))
- GOTO(out, rc = 1);
-
- EXIT;
- out:
- ldlm_resource_putref(res);
- l_unlock(&ns->ns_lock);
-
- if (lock) {
- ldlm_lock2handle(lock, lockh);
- if (lock->l_completion_ast)
- lock->l_completion_ast(lock, LDLM_FL_WAIT_NOREPROC);
- }
- if (rc)
- LDLM_DEBUG(lock, "matched");
- else
- LDLM_DEBUG_NOLOCK("not matched");
-
- if (old_lock)
- LDLM_LOCK_PUT(old_lock);
-
- return rc;
-}
-
-/* Returns a referenced lock */
-struct ldlm_lock *ldlm_lock_create(struct ldlm_namespace *ns,
- struct lustre_handle *parent_lock_handle,
- __u64 * res_id, __u32 type,
- ldlm_mode_t mode, void *data, __u32 data_len)
-{
- struct ldlm_resource *res, *parent_res = NULL;
- struct ldlm_lock *lock, *parent_lock = NULL;
-
- if (parent_lock_handle) {
- parent_lock = ldlm_handle2lock(parent_lock_handle);
- if (parent_lock)
- parent_res = parent_lock->l_resource;
- }
-
- res = ldlm_resource_get(ns, parent_res, res_id, type, 1);
- if (res == NULL)
- RETURN(NULL);
-
- lock = ldlm_lock_new(parent_lock, res);
- if (lock == NULL) {
- ldlm_resource_putref(res);
- RETURN(NULL);
- }
-
- lock->l_req_mode = mode;
- lock->l_data = data;
- lock->l_data_len = data_len;
-
- return lock;
-}
-
-/* Must be called with lock->l_lock and lock->l_resource->lr_lock not held */
-ldlm_error_t ldlm_lock_enqueue(struct ldlm_lock * lock,
- void *cookie, int cookie_len,
- int *flags,
- ldlm_completion_callback completion,
- ldlm_blocking_callback blocking)
-{
- struct ldlm_resource *res;
- int local;
- ldlm_res_policy policy;
- ENTRY;
-
- res = lock->l_resource;
- lock->l_blocking_ast = blocking;
-
- if (res->lr_type == LDLM_EXTENT)
- memcpy(&lock->l_extent, cookie, sizeof(lock->l_extent));
-
- /* policies are not executed on the client or during replay */
- local = res->lr_namespace->ns_client;
- if (!local && !(*flags & LDLM_FL_REPLAY) &&
- (policy = ldlm_res_policy_table[res->lr_type])) {
- int rc;
- rc = policy(lock, cookie, lock->l_req_mode, *flags, NULL);
-
- if (rc == ELDLM_LOCK_CHANGED) {
- res = lock->l_resource;
- *flags |= LDLM_FL_LOCK_CHANGED;
- } else if (rc == ELDLM_LOCK_ABORTED) {
- ldlm_lock_destroy(lock);
- RETURN(rc);
- }
- }
-
- l_lock(&res->lr_namespace->ns_lock);
- if (local && lock->l_req_mode == lock->l_granted_mode) {
- /* The server returned a blocked lock, but it was granted before
- * we got a chance to actually enqueue it. We don't need to do
- * anything else. */
- *flags &= ~(LDLM_FL_BLOCK_GRANTED |
- LDLM_FL_BLOCK_CONV | LDLM_FL_BLOCK_WAIT);
- GOTO(out, ELDLM_OK);
- }
-
- /* This distinction between local lock trees is very important; a client
- * namespace only has information about locks taken by that client, and
- * thus doesn't have enough information to decide for itself if it can
- * be granted (below). In this case, we do exactly what the server
- * tells us to do, as dictated by the 'flags'.
- *
- * We do exactly the same thing during recovery, when the server is
- * more or less trusting the clients not to lie.
- *
- * FIXME (bug 629283): Detect obvious lies by checking compatibility in
- * granted/converting queues. */
- ldlm_resource_unlink_lock(lock);
- if (local || (*flags & LDLM_FL_REPLAY)) {
- if (*flags & LDLM_FL_BLOCK_CONV)
- ldlm_resource_add_lock(res, res->lr_converting.prev,
- lock);
- else if (*flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED))
- ldlm_resource_add_lock(res, res->lr_waiting.prev, lock);
- else
- ldlm_grant_lock(lock);
- GOTO(out, ELDLM_OK);
- }
-
- /* FIXME: We may want to optimize by checking lr_most_restr */
- if (!list_empty(&res->lr_converting)) {
- ldlm_resource_add_lock(res, res->lr_waiting.prev, lock);
- *flags |= LDLM_FL_BLOCK_CONV;
- GOTO(out, ELDLM_OK);
- }
- if (!list_empty(&res->lr_waiting)) {
- ldlm_resource_add_lock(res, res->lr_waiting.prev, lock);
- *flags |= LDLM_FL_BLOCK_WAIT;
- GOTO(out, ELDLM_OK);
- }
- if (!ldlm_lock_compat(lock, 0)) {
- ldlm_resource_add_lock(res, res->lr_waiting.prev, lock);
- *flags |= LDLM_FL_BLOCK_GRANTED;
- GOTO(out, ELDLM_OK);
- }
-
- ldlm_grant_lock(lock);
- EXIT;
- out:
- l_unlock(&res->lr_namespace->ns_lock);
- /* Don't set 'completion_ast' until here so that if the lock is granted
- * immediately we don't do an unnecessary completion call. */
- lock->l_completion_ast = completion;
- return ELDLM_OK;
-}
-
-/* Must be called with namespace taken: queue is waiting or converting. */
-static int ldlm_reprocess_queue(struct ldlm_resource *res,
- struct list_head *queue)
-{
- struct list_head *tmp, *pos;
- ENTRY;
-
- list_for_each_safe(tmp, pos, queue) {
- struct ldlm_lock *pending;
- pending = list_entry(tmp, struct ldlm_lock, l_res_link);
-
- CDEBUG(D_INFO, "Reprocessing lock %p\n", pending);
-
- if (!ldlm_lock_compat(pending, 1))
- RETURN(1);
-
- list_del_init(&pending->l_res_link);
- ldlm_grant_lock(pending);
- }
-
- RETURN(0);
-}
-
-void ldlm_run_ast_work(struct list_head *rpc_list)
-{
- struct list_head *tmp, *pos;
- int rc;
- ENTRY;
-
- list_for_each_safe(tmp, pos, rpc_list) {
- struct ldlm_ast_work *w =
- list_entry(tmp, struct ldlm_ast_work, w_list);
-
- if (w->w_blocking)
- rc = w->w_lock->l_blocking_ast
- (w->w_lock, &w->w_desc, w->w_data,
- w->w_datalen, LDLM_CB_BLOCKING);
- else
- rc = w->w_lock->l_completion_ast(w->w_lock, w->w_flags);
- if (rc)
- CERROR("Failed AST - should clean & disconnect "
- "client\n");
- LDLM_LOCK_PUT(w->w_lock);
- list_del(&w->w_list);
- OBD_FREE(w, sizeof(*w));
- }
- EXIT;
-}
-
-/* Must be called with resource->lr_lock not taken. */
-void ldlm_reprocess_all(struct ldlm_resource *res)
-{
- struct list_head rpc_list = LIST_HEAD_INIT(rpc_list);
- ENTRY;
-
- /* Local lock trees don't get reprocessed. */
- if (res->lr_namespace->ns_client) {
- EXIT;
- return;
- }
-
- l_lock(&res->lr_namespace->ns_lock);
- res->lr_tmp = &rpc_list;
-
- ldlm_reprocess_queue(res, &res->lr_converting);
- if (list_empty(&res->lr_converting))
- ldlm_reprocess_queue(res, &res->lr_waiting);
-
- res->lr_tmp = NULL;
- l_unlock(&res->lr_namespace->ns_lock);
-
- ldlm_run_ast_work(&rpc_list);
- EXIT;
-}
-
-void ldlm_cancel_callback(struct ldlm_lock *lock)
-{
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- if (!(lock->l_flags & LDLM_FL_CANCEL)) {
- lock->l_flags |= LDLM_FL_CANCEL;
- if (lock->l_blocking_ast)
- lock->l_blocking_ast(lock, NULL, lock->l_data,
- lock->l_data_len,
- LDLM_CB_CANCELING);
- else
- LDLM_DEBUG(lock, "no blocking ast");
- }
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
-}
-
-void ldlm_lock_cancel(struct ldlm_lock *lock)
-{
- struct ldlm_resource *res;
- struct ldlm_namespace *ns;
- ENTRY;
-
- res = lock->l_resource;
- ns = res->lr_namespace;
-
- l_lock(&ns->ns_lock);
- if (lock->l_readers || lock->l_writers)
- LDLM_DEBUG(lock, "lock still has references");
-
- ldlm_cancel_callback(lock);
-
- ldlm_del_waiting_lock(lock);
- ldlm_resource_unlink_lock(lock);
- ldlm_lock_destroy(lock);
- l_unlock(&ns->ns_lock);
- EXIT;
-}
-
-int ldlm_lock_set_data(struct lustre_handle *lockh, void *data, int datalen)
-{
- struct ldlm_lock *lock = ldlm_handle2lock(lockh);
- ENTRY;
-
- if (lock == NULL)
- RETURN(-EINVAL);
-
- lock->l_data = data;
- lock->l_data_len = datalen;
-
- LDLM_LOCK_PUT(lock);
-
- RETURN(0);
-}
-
-void ldlm_cancel_locks_for_export(struct obd_export *exp)
-{
- struct list_head *iter, *n; /* MUST BE CALLED "n"! */
-
- list_for_each_safe(iter, n, &exp->exp_ldlm_data.led_held_locks) {
- struct ldlm_lock *lock;
- struct ldlm_resource *res;
- lock = list_entry(iter, struct ldlm_lock, l_export_chain);
- res = ldlm_resource_getref(lock->l_resource);
- LDLM_DEBUG(lock, "export %p", exp);
- ldlm_lock_cancel(lock);
- ldlm_reprocess_all(res);
- ldlm_resource_putref(res);
- }
-}
-
-struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode,
- int *flags)
-{
- struct list_head rpc_list = LIST_HEAD_INIT(rpc_list);
- struct ldlm_resource *res;
- struct ldlm_namespace *ns;
- int granted = 0;
- ENTRY;
-
- res = lock->l_resource;
- ns = res->lr_namespace;
-
- l_lock(&ns->ns_lock);
-
- lock->l_req_mode = new_mode;
- ldlm_resource_unlink_lock(lock);
-
- /* If this is a local resource, put it on the appropriate list. */
- if (res->lr_namespace->ns_client) {
- if (*flags & (LDLM_FL_BLOCK_CONV | LDLM_FL_BLOCK_GRANTED))
- ldlm_resource_add_lock(res, res->lr_converting.prev,
- lock);
- else {
- /* This should never happen, because of the way the
- * server handles conversions. */
- LBUG();
-
- res->lr_tmp = &rpc_list;
- ldlm_grant_lock(lock);
- res->lr_tmp = NULL;
- granted = 1;
- /* FIXME: completion handling not with ns_lock held ! */
- if (lock->l_completion_ast)
- lock->l_completion_ast(lock, 0);
- }
- } else {
- /* FIXME: We should try the conversion right away and possibly
- * return success without the need for an extra AST */
- ldlm_resource_add_lock(res, res->lr_converting.prev, lock);
- *flags |= LDLM_FL_BLOCK_CONV;
- }
-
- l_unlock(&ns->ns_lock);
-
- if (granted)
- ldlm_run_ast_work(&rpc_list);
- RETURN(res);
-}
-
-void ldlm_lock_dump(struct ldlm_lock *lock)
-{
- char ver[128];
-
- if (!(portal_debug & D_OTHER))
- return;
-
- if (RES_VERSION_SIZE != 4)
- LBUG();
-
- if (!lock) {
- CDEBUG(D_OTHER, " NULL LDLM lock\n");
- return;
- }
-
- snprintf(ver, sizeof(ver), "%x %x %x %x",
- lock->l_version[0], lock->l_version[1],
- lock->l_version[2], lock->l_version[3]);
-
- CDEBUG(D_OTHER, " -- Lock dump: %p (%s)\n", lock, ver);
- if (lock->l_export && lock->l_export->exp_connection)
- CDEBUG(D_OTHER, " Node: NID %x (rhandle: "LPX64")\n",
- lock->l_export->exp_connection->c_peer.peer_nid,
- lock->l_remote_handle.addr);
- else
- CDEBUG(D_OTHER, " Node: local\n");
- CDEBUG(D_OTHER, " Parent: %p\n", lock->l_parent);
- CDEBUG(D_OTHER, " Resource: %p ("LPD64")\n", lock->l_resource,
- lock->l_resource->lr_name[0]);
- CDEBUG(D_OTHER, " Requested mode: %d, granted mode: %d\n",
- (int)lock->l_req_mode, (int)lock->l_granted_mode);
- CDEBUG(D_OTHER, " Readers: %u ; Writers; %u\n",
- lock->l_readers, lock->l_writers);
- if (lock->l_resource->lr_type == LDLM_EXTENT)
- CDEBUG(D_OTHER, " Extent: %Lu -> %Lu\n",
- (unsigned long long)lock->l_extent.start,
- (unsigned long long)lock->l_extent.end);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * Author: Peter Braam <braam@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_LDLM
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/lustre_dlm.h>
-#include <linux/init.h>
-#include <linux/obd_class.h>
-
-extern kmem_cache_t *ldlm_resource_slab;
-extern kmem_cache_t *ldlm_lock_slab;
-extern struct lustre_lock ldlm_handle_lock;
-extern struct list_head ldlm_namespace_list;
-extern int (*mds_reint_p)(int offset, struct ptlrpc_request *req);
-extern int (*mds_getattr_name_p)(int offset, struct ptlrpc_request *req);
-
-inline unsigned long round_timeout(unsigned long timeout)
-{
- return ((timeout / HZ) + 1) * HZ;
-}
-
-static struct list_head waiting_locks_list;
-static spinlock_t waiting_locks_spinlock;
-static struct timer_list waiting_locks_timer;
-static int ldlm_already_setup = 0;
-
-static void waiting_locks_callback(unsigned long unused)
-{
- struct list_head *liter, *n;
-
- spin_lock_bh(&waiting_locks_spinlock);
- list_for_each_safe(liter, n, &waiting_locks_list) {
- struct ldlm_lock *l = list_entry(liter, struct ldlm_lock,
- l_pending_chain);
- if (l->l_callback_timeout > jiffies)
- break;
- LDLM_DEBUG(l, "timer expired, recovering exp %p on conn %p",
- l->l_export, l->l_export->exp_connection);
- recovd_conn_fail(l->l_export->exp_connection);
- }
- spin_unlock_bh(&waiting_locks_spinlock);
-}
-
-/*
- * Indicate that we're waiting for a client to call us back cancelling a given
- * lock. We add it to the pending-callback chain, and schedule the lock-timeout
- * timer to fire appropriately. (We round up to the next second, to avoid
- * floods of timer firings during periods of high lock contention and traffic).
- */
-static int ldlm_add_waiting_lock(struct ldlm_lock *lock)
-{
- unsigned long timeout_rounded;
- ENTRY;
-
- LASSERT(list_empty(&lock->l_pending_chain));
-
- spin_lock_bh(&waiting_locks_spinlock);
- lock->l_callback_timeout = jiffies + (obd_timeout * HZ / 2);
-
- timeout_rounded = round_timeout(lock->l_callback_timeout);
-
- if (timeout_rounded < waiting_locks_timer.expires ||
- !timer_pending(&waiting_locks_timer)) {
- mod_timer(&waiting_locks_timer, timeout_rounded);
- }
- list_add_tail(&lock->l_pending_chain, &waiting_locks_list); /* FIFO */
- spin_unlock_bh(&waiting_locks_spinlock);
- RETURN(1);
-}
-
-/*
- * Remove a lock from the pending list, likely because it had its cancellation
- * callback arrive without incident. This adjusts the lock-timeout timer if
- * needed. Returns 0 if the lock wasn't pending after all, 1 if it was.
- */
-int ldlm_del_waiting_lock(struct ldlm_lock *lock)
-{
- struct list_head *list_next;
-
- ENTRY;
-
- spin_lock_bh(&waiting_locks_spinlock);
-
- if (list_empty(&lock->l_pending_chain)) {
- spin_unlock_bh(&waiting_locks_spinlock);
- RETURN(0);
- }
-
- list_next = lock->l_pending_chain.next;
- if (lock->l_pending_chain.prev == &waiting_locks_list) {
- /* Removing the head of the list, adjust timer. */
- if (list_next == &waiting_locks_list) {
- /* No more, just cancel. */
- del_timer(&waiting_locks_timer);
- } else {
- struct ldlm_lock *next;
- next = list_entry(list_next, struct ldlm_lock,
- l_pending_chain);
- mod_timer(&waiting_locks_timer,
- round_timeout(next->l_callback_timeout));
- }
- }
- list_del_init(&lock->l_pending_chain);
- spin_unlock_bh(&waiting_locks_spinlock);
- RETURN(1);
-}
-
-static int ldlm_server_blocking_ast(struct ldlm_lock *lock,
- struct ldlm_lock_desc *desc,
- void *data, __u32 data_len, int flag)
-{
- struct ldlm_request *body;
- struct ptlrpc_request *req;
- int rc = 0, size = sizeof(*body);
- ENTRY;
-
- if (flag == LDLM_CB_CANCELING) {
- /* Don't need to do anything here. */
- RETURN(0);
- }
-
- req = ptlrpc_prep_req(&lock->l_export->exp_ldlm_data.led_import,
- LDLM_BL_CALLBACK, 1, &size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- memcpy(&body->lock_handle1, &lock->l_remote_handle,
- sizeof(body->lock_handle1));
- memcpy(&body->lock_desc, desc, sizeof(*desc));
-
- LDLM_DEBUG(lock, "server preparing blocking AST");
- req->rq_replen = 0; /* no reply needed */
-
- ldlm_add_waiting_lock(lock);
- (void)ptl_send_rpc(req);
-
- /* not waiting for reply */
- ptlrpc_req_finished(req);
-
- RETURN(rc);
-}
-
-static int ldlm_server_completion_ast(struct ldlm_lock *lock, int flags)
-{
- struct ldlm_request *body;
- struct ptlrpc_request *req;
- int rc = 0, size = sizeof(*body);
- ENTRY;
-
- if (lock == NULL) {
- LBUG();
- RETURN(-EINVAL);
- }
-
- req = ptlrpc_prep_req(&lock->l_export->exp_ldlm_data.led_import,
- LDLM_CP_CALLBACK, 1, &size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- memcpy(&body->lock_handle1, &lock->l_remote_handle,
- sizeof(body->lock_handle1));
- body->lock_flags = flags;
- ldlm_lock2desc(lock, &body->lock_desc);
-
- LDLM_DEBUG(lock, "server preparing completion AST");
- req->rq_replen = 0; /* no reply needed */
-
- (void)ptl_send_rpc(req);
-
- /* not waiting for reply */
- ptlrpc_req_finished(req);
-
- RETURN(rc);
-}
-
-int ldlm_handle_enqueue(struct ptlrpc_request *req)
-{
- struct obd_device *obddev = req->rq_export->exp_obd;
- struct ldlm_reply *dlm_rep;
- struct ldlm_request *dlm_req;
- int rc, size = sizeof(*dlm_rep), cookielen = 0;
- __u32 flags;
- ldlm_error_t err;
- struct ldlm_lock *lock = NULL;
- void *cookie = NULL;
- ENTRY;
-
- LDLM_DEBUG_NOLOCK("server-side enqueue handler START");
-
- dlm_req = lustre_msg_buf(req->rq_reqmsg, 0);
- flags = dlm_req->lock_flags;
- if (dlm_req->lock_desc.l_resource.lr_type == LDLM_PLAIN &&
- (flags & LDLM_FL_HAS_INTENT)) {
- /* In this case, the reply buffer is allocated deep in
- * local_lock_enqueue by the policy function. */
- cookie = req;
- cookielen = sizeof(*req);
- } else {
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen,
- &req->rq_repmsg);
- if (rc) {
- CERROR("out of memory\n");
- RETURN(-ENOMEM);
- }
- if (dlm_req->lock_desc.l_resource.lr_type == LDLM_EXTENT) {
- cookie = &dlm_req->lock_desc.l_extent;
- cookielen = sizeof(struct ldlm_extent);
- }
- }
-
- /* XXX notice that this lock has no callback data: of course the
- export would be exactly what we may want to use here... */
- lock = ldlm_lock_create(obddev->obd_namespace,
- &dlm_req->lock_handle2,
- dlm_req->lock_desc.l_resource.lr_name,
- dlm_req->lock_desc.l_resource.lr_type,
- dlm_req->lock_desc.l_req_mode, NULL, 0);
- if (!lock)
- GOTO(out, err = -ENOMEM);
-
- memcpy(&lock->l_remote_handle, &dlm_req->lock_handle1,
- sizeof(lock->l_remote_handle));
- LDLM_DEBUG(lock, "server-side enqueue handler, new lock created");
-
- err = ldlm_lock_enqueue(lock, cookie, cookielen, &flags,
- ldlm_server_completion_ast,
- ldlm_server_blocking_ast);
- if (err != ELDLM_OK)
- GOTO(out, err);
-
- dlm_rep = lustre_msg_buf(req->rq_repmsg, 0);
- dlm_rep->lock_flags = flags;
-
- ldlm_lock2handle(lock, &dlm_rep->lock_handle);
- if (dlm_req->lock_desc.l_resource.lr_type == LDLM_EXTENT)
- memcpy(&dlm_rep->lock_extent, &lock->l_extent,
- sizeof(lock->l_extent));
- if (dlm_rep->lock_flags & LDLM_FL_LOCK_CHANGED) {
- memcpy(dlm_rep->lock_resource_name, lock->l_resource->lr_name,
- sizeof(dlm_rep->lock_resource_name));
- dlm_rep->lock_mode = lock->l_req_mode;
- }
-
- lock->l_export = req->rq_export;
- if (lock->l_export) {
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- list_add(&lock->l_export_chain,
- &lock->l_export->exp_ldlm_data.led_held_locks);
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- }
-
- EXIT;
- out:
- if (lock)
- LDLM_DEBUG(lock, "server-side enqueue handler, sending reply"
- "(err=%d)", err);
- req->rq_status = err;
-
- if (lock) {
- if (!err)
- ldlm_reprocess_all(lock->l_resource);
- LDLM_LOCK_PUT(lock);
- }
- LDLM_DEBUG_NOLOCK("server-side enqueue handler END (lock %p)", lock);
-
- return 0;
-}
-
-int ldlm_handle_convert(struct ptlrpc_request *req)
-{
- struct ldlm_request *dlm_req;
- struct ldlm_reply *dlm_rep;
- struct ldlm_lock *lock;
- int rc, size = sizeof(*dlm_rep);
- ENTRY;
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc) {
- CERROR("out of memory\n");
- RETURN(-ENOMEM);
- }
- dlm_req = lustre_msg_buf(req->rq_reqmsg, 0);
- dlm_rep = lustre_msg_buf(req->rq_repmsg, 0);
- dlm_rep->lock_flags = dlm_req->lock_flags;
-
- lock = ldlm_handle2lock(&dlm_req->lock_handle1);
- if (!lock) {
- req->rq_status = EINVAL;
- } else {
- LDLM_DEBUG(lock, "server-side convert handler START");
- ldlm_lock_convert(lock, dlm_req->lock_desc.l_req_mode,
- &dlm_rep->lock_flags);
- if (ldlm_del_waiting_lock(lock))
- CDEBUG(D_DLMTRACE, "converted waiting lock %p\n", lock);
- req->rq_status = 0;
- }
-
- if (lock) {
- ldlm_reprocess_all(lock->l_resource);
- LDLM_DEBUG(lock, "server-side convert handler END");
- LDLM_LOCK_PUT(lock);
- } else
- LDLM_DEBUG_NOLOCK("server-side convert handler END");
-
- RETURN(0);
-}
-
-int ldlm_handle_cancel(struct ptlrpc_request *req)
-{
- struct ldlm_request *dlm_req;
- struct ldlm_lock *lock;
- int rc;
- ENTRY;
-
- rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc) {
- CERROR("out of memory\n");
- RETURN(-ENOMEM);
- }
- dlm_req = lustre_msg_buf(req->rq_reqmsg, 0);
- if (!dlm_req) {
- CERROR("bad request buffer for cancel\n");
- RETURN(-EINVAL);
- }
-
- lock = ldlm_handle2lock(&dlm_req->lock_handle1);
- if (!lock) {
- LDLM_DEBUG_NOLOCK("server-side cancel handler stale lock (lock "
- "%p)", (void *)(unsigned long)
- dlm_req->lock_handle1.addr);
- req->rq_status = ESTALE;
- } else {
- LDLM_DEBUG(lock, "server-side cancel handler START");
- ldlm_lock_cancel(lock);
- if (ldlm_del_waiting_lock(lock))
- CDEBUG(D_DLMTRACE, "cancelled waiting lock %p\n", lock);
- req->rq_status = 0;
- }
-
- if (ptlrpc_reply(req->rq_svc, req) != 0)
- LBUG();
-
- if (lock) {
- ldlm_reprocess_all(lock->l_resource);
- LDLM_DEBUG(lock, "server-side cancel handler END");
- LDLM_LOCK_PUT(lock);
- }
-
- RETURN(0);
-}
-
-static int ldlm_handle_bl_callback(struct ptlrpc_request *req)
-{
- struct ldlm_request *dlm_req;
- struct ldlm_lock *lock;
- int do_ast;
- ENTRY;
-
- OBD_FAIL_RETURN(OBD_FAIL_OSC_LOCK_BL_AST, 0);
-
- dlm_req = lustre_msg_buf(req->rq_reqmsg, 0);
-
- lock = ldlm_handle2lock(&dlm_req->lock_handle1);
- if (!lock) {
- CERROR("blocking callback on lock "LPX64" - lock disappeared\n",
- dlm_req->lock_handle1.addr);
- RETURN(0);
- }
-
- LDLM_DEBUG(lock, "client blocking AST callback handler START");
-
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- lock->l_flags |= LDLM_FL_CBPENDING;
- do_ast = (!lock->l_readers && !lock->l_writers);
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
-
- if (do_ast) {
- LDLM_DEBUG(lock, "already unused, calling "
- "callback (%p)", lock->l_blocking_ast);
- if (lock->l_blocking_ast != NULL) {
- lock->l_blocking_ast(lock, &dlm_req->lock_desc,
- lock->l_data, lock->l_data_len,
- LDLM_CB_BLOCKING);
- }
- } else
- LDLM_DEBUG(lock, "Lock still has references, will be"
- " cancelled later");
-
- LDLM_DEBUG(lock, "client blocking callback handler END");
- LDLM_LOCK_PUT(lock);
- RETURN(0);
-}
-
-static int ldlm_handle_cp_callback(struct ptlrpc_request *req)
-{
- struct list_head ast_list = LIST_HEAD_INIT(ast_list);
- struct ldlm_request *dlm_req;
- struct ldlm_lock *lock;
- ENTRY;
-
- OBD_FAIL_RETURN(OBD_FAIL_OSC_LOCK_CP_AST, 0);
-
- dlm_req = lustre_msg_buf(req->rq_reqmsg, 0);
-
- lock = ldlm_handle2lock(&dlm_req->lock_handle1);
- if (!lock) {
- CERROR("completion callback on lock "LPX64" - lock "
- "disappeared\n", dlm_req->lock_handle1.addr);
- RETURN(0);
- }
-
- LDLM_DEBUG(lock, "client completion callback handler START");
-
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
-
- /* If we receive the completion AST before the actual enqueue returned,
- * then we might need to switch lock modes, resources, or extents. */
- if (dlm_req->lock_desc.l_granted_mode != lock->l_req_mode) {
- lock->l_req_mode = dlm_req->lock_desc.l_granted_mode;
- LDLM_DEBUG(lock, "completion AST, new lock mode");
- }
- if (lock->l_resource->lr_type == LDLM_EXTENT)
- memcpy(&lock->l_extent, &dlm_req->lock_desc.l_extent,
- sizeof(lock->l_extent));
- ldlm_resource_unlink_lock(lock);
- if (memcmp(dlm_req->lock_desc.l_resource.lr_name,
- lock->l_resource->lr_name,
- sizeof(__u64) * RES_NAME_SIZE) != 0) {
- ldlm_lock_change_resource(lock,
- dlm_req->lock_desc.l_resource.lr_name);
- LDLM_DEBUG(lock, "completion AST, new resource");
- }
- lock->l_resource->lr_tmp = &ast_list;
- ldlm_grant_lock(lock);
- lock->l_resource->lr_tmp = NULL;
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- LDLM_DEBUG(lock, "callback handler finished, about to run_ast_work");
- LDLM_LOCK_PUT(lock);
-
- ldlm_run_ast_work(&ast_list);
-
- LDLM_DEBUG_NOLOCK("client completion callback handler END (lock %p)",
- lock);
- RETURN(0);
-}
-
-static int ldlm_callback_handler(struct ptlrpc_request *req)
-{
- int rc;
- ENTRY;
-
- rc = lustre_unpack_msg(req->rq_reqmsg, req->rq_reqlen);
- if (rc) {
- CERROR("lustre_ldlm: Invalid request: %d\n", rc);
- RETURN(rc);
- }
-
- if (req->rq_export == NULL) {
- CERROR("operation %d with bad export (ptl req %d/rep %d)\n",
- req->rq_reqmsg->opc, req->rq_request_portal,
- req->rq_reply_portal);
- CERROR("--> export addr: "LPX64", cookie: "LPX64"\n",
- req->rq_reqmsg->addr, req->rq_reqmsg->cookie);
- CERROR("--> ignoring this error as a temporary workaround! "
- "beware!\n");
- //RETURN(-ENOTCONN);
- }
-
- switch (req->rq_reqmsg->opc) {
- case LDLM_BL_CALLBACK:
- CDEBUG(D_INODE, "blocking ast\n");
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_BL_CALLBACK, 0);
- rc = ldlm_handle_bl_callback(req);
- RETURN(rc);
- case LDLM_CP_CALLBACK:
- CDEBUG(D_INODE, "completion ast\n");
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_CP_CALLBACK, 0);
- rc = ldlm_handle_cp_callback(req);
- RETURN(rc);
-
- default:
- CERROR("invalid opcode %d\n", req->rq_reqmsg->opc);
- RETURN(-EINVAL);
- }
-
- RETURN(0);
-}
-
-
-static int ldlm_cancel_handler(struct ptlrpc_request *req)
-{
- int rc;
- ENTRY;
-
- rc = lustre_unpack_msg(req->rq_reqmsg, req->rq_reqlen);
- if (rc) {
- CERROR("lustre_ldlm: Invalid request: %d\n", rc);
- RETURN(rc);
- }
-
- if (req->rq_export == NULL) {
- CERROR("operation %d with bad export (ptl req %d/rep %d)\n",
- req->rq_reqmsg->opc, req->rq_request_portal,
- req->rq_reply_portal);
- CERROR("--> export addr: "LPX64", cookie: "LPX64"\n",
- req->rq_reqmsg->addr, req->rq_reqmsg->cookie);
- CERROR("--> ignoring this error as a temporary workaround! "
- "beware!\n");
- //RETURN(-ENOTCONN);
- }
-
- switch (req->rq_reqmsg->opc) {
-
- /* XXX FIXME move this back to mds/handler.c, bug 625069 */
- case LDLM_CANCEL:
- CDEBUG(D_INODE, "cancel\n");
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_CANCEL, 0);
- rc = ldlm_handle_cancel(req);
- if (rc)
- break;
- RETURN(0);
-
- default:
- CERROR("invalid opcode %d\n", req->rq_reqmsg->opc);
- RETURN(-EINVAL);
- }
-
- RETURN(0);
-}
-
-
-static int ldlm_iocontrol(long cmd, struct lustre_handle *conn, int len,
- void *karg, void *uarg)
-{
- struct obd_device *obddev = class_conn2obd(conn);
- struct ptlrpc_connection *connection;
- int err = 0;
- ENTRY;
-
- if (_IOC_TYPE(cmd) != IOC_LDLM_TYPE || _IOC_NR(cmd) < IOC_LDLM_MIN_NR ||
- _IOC_NR(cmd) > IOC_LDLM_MAX_NR) {
- CDEBUG(D_IOCTL, "invalid ioctl (type %ld, nr %ld, size %ld)\n",
- _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
- RETURN(-EINVAL);
- }
-
- OBD_ALLOC(obddev->u.ldlm.ldlm_client,
- sizeof(*obddev->u.ldlm.ldlm_client));
- connection = ptlrpc_uuid_to_connection("ldlm");
- if (!connection)
- CERROR("No LDLM UUID found: assuming ldlm is local.\n");
-
- switch (cmd) {
- case IOC_LDLM_TEST:
- err = ldlm_test(obddev, conn);
- CERROR("-- done err %d\n", err);
- GOTO(out, err);
- case IOC_LDLM_DUMP:
- ldlm_dump_all_namespaces();
- GOTO(out, err);
- default:
- GOTO(out, err = -EINVAL);
- }
-
- out:
- if (connection)
- ptlrpc_put_connection(connection);
- OBD_FREE(obddev->u.ldlm.ldlm_client,
- sizeof(*obddev->u.ldlm.ldlm_client));
- return err;
-}
-
-static int ldlm_setup(struct obd_device *obddev, obd_count len, void *buf)
-{
- struct ldlm_obd *ldlm = &obddev->u.ldlm;
- int rc, i;
- ENTRY;
-
- if (ldlm_already_setup)
- RETURN(-EALREADY);
-
- MOD_INC_USE_COUNT;
-
- rc = ldlm_proc_setup(obddev);
- if (rc != 0)
- GOTO(out_dec, rc);
-
- ldlm->ldlm_cb_service =
- ptlrpc_init_svc(LDLM_NEVENTS, LDLM_NBUFS, LDLM_BUFSIZE,
- LDLM_MAXREQSIZE, LDLM_CB_REQUEST_PORTAL,
- LDLM_CB_REPLY_PORTAL, "self",
- ldlm_callback_handler, "ldlm_cbd");
-
- if (!ldlm->ldlm_cb_service) {
- CERROR("failed to start service\n");
- GOTO(out_proc, rc = -ENOMEM);
- }
-
- ldlm->ldlm_cancel_service =
- ptlrpc_init_svc(LDLM_NEVENTS, LDLM_NBUFS, LDLM_BUFSIZE,
- LDLM_MAXREQSIZE, LDLM_CANCEL_REQUEST_PORTAL,
- LDLM_CANCEL_REPLY_PORTAL, "self",
- ldlm_cancel_handler, "ldlm_canceld");
-
- if (!ldlm->ldlm_cancel_service) {
- CERROR("failed to start service\n");
- GOTO(out_proc, rc = -ENOMEM);
- }
-
- for (i = 0; i < LDLM_NUM_THREADS; i++) {
- char name[32];
- sprintf(name, "ldlm_cn_%02d", i);
- rc = ptlrpc_start_thread(obddev, ldlm->ldlm_cancel_service,
- name);
- if (rc) {
- CERROR("cannot start LDLM thread #%d: rc %d\n", i, rc);
- LBUG();
- GOTO(out_thread, rc);
- }
- }
-
- for (i = 0; i < LDLM_NUM_THREADS; i++) {
- char name[32];
- sprintf(name, "ldlm_cb_%02d", i);
- rc = ptlrpc_start_thread(obddev, ldlm->ldlm_cb_service, name);
- if (rc) {
- CERROR("cannot start LDLM thread #%d: rc %d\n", i, rc);
- LBUG();
- GOTO(out_thread, rc);
- }
- }
-
- INIT_LIST_HEAD(&waiting_locks_list);
- spin_lock_init(&waiting_locks_spinlock);
- waiting_locks_timer.function = waiting_locks_callback;
- waiting_locks_timer.data = 0;
- init_timer(&waiting_locks_timer);
-
- ldlm_already_setup = 1;
-
- RETURN(0);
-
- out_thread:
- ptlrpc_stop_all_threads(ldlm->ldlm_cancel_service);
- ptlrpc_unregister_service(ldlm->ldlm_cancel_service);
- ptlrpc_stop_all_threads(ldlm->ldlm_cb_service);
- ptlrpc_unregister_service(ldlm->ldlm_cb_service);
-
- out_proc:
- ldlm_proc_cleanup(obddev);
-
- out_dec:
- MOD_DEC_USE_COUNT;
- return rc;
-}
-
-static int ldlm_cleanup(struct obd_device *obddev)
-{
- struct ldlm_obd *ldlm = &obddev->u.ldlm;
- ENTRY;
-
- if (!list_empty(&ldlm_namespace_list)) {
- CERROR("ldlm still has namespaces; clean these up first.\n");
- RETURN(-EBUSY);
- }
-
- ptlrpc_stop_all_threads(ldlm->ldlm_cb_service);
- ptlrpc_unregister_service(ldlm->ldlm_cb_service);
- ptlrpc_stop_all_threads(ldlm->ldlm_cancel_service);
- ptlrpc_unregister_service(ldlm->ldlm_cancel_service);
- ldlm_proc_cleanup(obddev);
-
- ldlm_already_setup = 0;
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-static int ldlm_connect(struct lustre_handle *conn, struct obd_device *src,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- return class_connect(conn, src, cluuid);
-}
-
-struct obd_ops ldlm_obd_ops = {
- o_iocontrol: ldlm_iocontrol,
- o_setup: ldlm_setup,
- o_cleanup: ldlm_cleanup,
- o_connect: ldlm_connect,
- o_disconnect: class_disconnect
-};
-
-static int __init ldlm_init(void)
-{
- int rc = class_register_type(&ldlm_obd_ops, 0, OBD_LDLM_DEVICENAME);
- if (rc != 0)
- return rc;
-
- ldlm_resource_slab = kmem_cache_create("ldlm_resources",
- sizeof(struct ldlm_resource), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (ldlm_resource_slab == NULL)
- return -ENOMEM;
-
- ldlm_lock_slab = kmem_cache_create("ldlm_locks",
- sizeof(struct ldlm_lock), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (ldlm_lock_slab == NULL) {
- kmem_cache_destroy(ldlm_resource_slab);
- return -ENOMEM;
- }
-
- l_lock_init(&ldlm_handle_lock);
-
- return 0;
-}
-
-static void __exit ldlm_exit(void)
-{
- class_unregister_type(OBD_LDLM_DEVICENAME);
- if (kmem_cache_destroy(ldlm_resource_slab) != 0)
- CERROR("couldn't free ldlm resource slab\n");
- if (kmem_cache_destroy(ldlm_lock_slab) != 0)
- CERROR("couldn't free ldlm lock slab\n");
-}
-
-EXPORT_SYMBOL(ldlm_completion_ast);
-EXPORT_SYMBOL(ldlm_handle_enqueue);
-EXPORT_SYMBOL(ldlm_handle_cancel);
-EXPORT_SYMBOL(ldlm_handle_convert);
-EXPORT_SYMBOL(ldlm_register_intent);
-EXPORT_SYMBOL(ldlm_unregister_intent);
-EXPORT_SYMBOL(ldlm_lockname);
-EXPORT_SYMBOL(ldlm_typename);
-EXPORT_SYMBOL(__ldlm_handle2lock);
-EXPORT_SYMBOL(ldlm_lock2handle);
-EXPORT_SYMBOL(ldlm_lock_put);
-EXPORT_SYMBOL(ldlm_lock_match);
-EXPORT_SYMBOL(ldlm_lock_addref);
-EXPORT_SYMBOL(ldlm_lock_decref);
-EXPORT_SYMBOL(ldlm_lock_change_resource);
-EXPORT_SYMBOL(ldlm_lock_set_data);
-EXPORT_SYMBOL(ldlm_cli_convert);
-EXPORT_SYMBOL(ldlm_cli_enqueue);
-EXPORT_SYMBOL(ldlm_cli_cancel);
-EXPORT_SYMBOL(ldlm_cli_cancel_unused);
-EXPORT_SYMBOL(ldlm_match_or_enqueue);
-EXPORT_SYMBOL(ldlm_it2str);
-EXPORT_SYMBOL(ldlm_test);
-EXPORT_SYMBOL(ldlm_regression_start);
-EXPORT_SYMBOL(ldlm_regression_stop);
-EXPORT_SYMBOL(ldlm_lock_dump);
-EXPORT_SYMBOL(ldlm_namespace_new);
-EXPORT_SYMBOL(ldlm_namespace_cleanup);
-EXPORT_SYMBOL(ldlm_namespace_free);
-EXPORT_SYMBOL(ldlm_namespace_dump);
-EXPORT_SYMBOL(ldlm_cancel_locks_for_export);
-EXPORT_SYMBOL(ldlm_replay_locks);
-EXPORT_SYMBOL(ldlm_resource_foreach);
-EXPORT_SYMBOL(ldlm_namespace_foreach);
-EXPORT_SYMBOL(l_lock);
-EXPORT_SYMBOL(l_unlock);
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Lock Management Module v0.1");
-MODULE_LICENSE("GPL");
-
-module_init(ldlm_init);
-module_exit(ldlm_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_LDLM
-
-#include <linux/lustre_dlm.h>
-#include <linux/obd_class.h>
-#include <linux/obd.h>
-
-static int interrupted_completion_wait(void *data)
-{
- RETURN(1);
-}
-
-static int expired_completion_wait(void *data)
-{
- struct ldlm_lock *lock = data;
- struct ptlrpc_connection *conn;
- struct obd_device *obd;
-
- if (!lock)
- CERROR("NULL lock\n");
- else if (!lock->l_connh)
- CERROR("lock %p has NULL connh\n", lock);
- else if (!(obd = class_conn2obd(lock->l_connh)))
- CERROR("lock %p has NULL obd\n", lock);
- else if (!(conn = obd->u.cli.cl_import.imp_connection))
- CERROR("lock %p has NULL connection\n", lock);
- else
- class_signal_connection_failure(conn);
- RETURN(0);
-}
-
-int ldlm_completion_ast(struct ldlm_lock *lock, int flags)
-{
- struct l_wait_info lwi =
- LWI_TIMEOUT_INTR(obd_timeout * HZ, expired_completion_wait,
- interrupted_completion_wait, lock);
- int rc = 0;
- ENTRY;
-
- if (flags == LDLM_FL_WAIT_NOREPROC)
- goto noreproc;
-
- if (flags == 0) {
- wake_up(&lock->l_waitq);
- RETURN(0);
- }
-
- if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
- LDLM_FL_BLOCK_CONV)))
- RETURN(0);
-
- LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock, "
- "sleeping");
- ldlm_lock_dump(lock);
- ldlm_reprocess_all(lock->l_resource);
-
- noreproc:
- /* Go to sleep until the lock is granted or cancelled. */
- rc = l_wait_event(lock->l_waitq,
- ((lock->l_req_mode == lock->l_granted_mode) ||
- lock->l_destroyed), &lwi);
-
- if (lock->l_destroyed) {
- LDLM_DEBUG(lock, "client-side enqueue waking up: destroyed");
- RETURN(-EIO);
- }
-
- if (rc) {
- LDLM_DEBUG(lock, "client-side enqueue waking up: failed (%d)",
- rc);
- RETURN(rc);
- }
-
- LDLM_DEBUG(lock, "client-side enqueue waking up: granted");
- RETURN(0);
-}
-
-static int ldlm_cli_enqueue_local(struct ldlm_namespace *ns,
- struct lustre_handle *parent_lockh,
- __u64 *res_id,
- __u32 type,
- void *cookie, int cookielen,
- ldlm_mode_t mode,
- int *flags,
- ldlm_completion_callback completion,
- ldlm_blocking_callback blocking,
- void *data,
- __u32 data_len,
- struct lustre_handle *lockh)
-{
- struct ldlm_lock *lock;
- int err;
- ENTRY;
-
- if (ns->ns_client) {
- CERROR("Trying to enqueue local lock in a shadow namespace\n");
- LBUG();
- }
-
- lock = ldlm_lock_create(ns, parent_lockh, res_id, type, mode, data,
- data_len);
- if (!lock)
- GOTO(out_nolock, err = -ENOMEM);
- LDLM_DEBUG(lock, "client-side local enqueue handler, new lock created");
-
- ldlm_lock_addref_internal(lock, mode);
- ldlm_lock2handle(lock, lockh);
- lock->l_connh = NULL;
-
- err = ldlm_lock_enqueue(lock, cookie, cookielen, flags, completion,
- blocking);
- if (err != ELDLM_OK)
- GOTO(out, err);
-
- if (type == LDLM_EXTENT)
- memcpy(cookie, &lock->l_extent, sizeof(lock->l_extent));
- if ((*flags) & LDLM_FL_LOCK_CHANGED)
- memcpy(res_id, lock->l_resource->lr_name, sizeof(*res_id));
-
- LDLM_DEBUG_NOLOCK("client-side local enqueue handler END (lock %p)",
- lock);
-
- if (lock->l_completion_ast)
- lock->l_completion_ast(lock, *flags);
-
- LDLM_DEBUG(lock, "client-side local enqueue END");
- EXIT;
- out:
- LDLM_LOCK_PUT(lock);
- out_nolock:
- return err;
-}
-
-int ldlm_cli_enqueue(struct lustre_handle *connh,
- struct ptlrpc_request *req,
- struct ldlm_namespace *ns,
- struct lustre_handle *parent_lock_handle,
- __u64 *res_id,
- __u32 type,
- void *cookie, int cookielen,
- ldlm_mode_t mode,
- int *flags,
- ldlm_completion_callback completion,
- ldlm_blocking_callback blocking,
- void *data,
- __u32 data_len,
- struct lustre_handle *lockh)
-{
- struct ldlm_lock *lock;
- struct ldlm_request *body;
- struct ldlm_reply *reply;
- int rc, size = sizeof(*body), req_passed_in = 1, is_replay;
- ENTRY;
-
- is_replay = *flags & LDLM_FL_REPLAY;
- LASSERT(connh != NULL || !is_replay);
-
- if (connh == NULL)
- return ldlm_cli_enqueue_local(ns, parent_lock_handle, res_id,
- type, cookie, cookielen, mode,
- flags, completion, blocking, data,
- data_len, lockh);
-
- /* If we're replaying this lock, just check some invariants.
- * If we're creating a new lock, get everything all setup nice. */
- if (is_replay) {
- lock = ldlm_handle2lock(lockh);
- LDLM_DEBUG(lock, "client-side enqueue START");
- LASSERT(connh == lock->l_connh);
- } else {
- lock = ldlm_lock_create(ns, parent_lock_handle, res_id, type,
- mode, data, data_len);
- if (lock == NULL)
- GOTO(out_nolock, rc = -ENOMEM);
- LDLM_DEBUG(lock, "client-side enqueue START");
- /* for the local lock, add the reference */
- ldlm_lock_addref_internal(lock, mode);
- ldlm_lock2handle(lock, lockh);
- if (type == LDLM_EXTENT)
- memcpy(&lock->l_extent, cookie,
- sizeof(body->lock_desc.l_extent));
- }
-
- if (req == NULL) {
- req = ptlrpc_prep_req(class_conn2cliimp(connh), LDLM_ENQUEUE, 1,
- &size, NULL);
- if (!req)
- GOTO(out, rc = -ENOMEM);
- req_passed_in = 0;
- } else if (req->rq_reqmsg->buflens[0] != sizeof(*body))
- LBUG();
-
- /* Dump lock data into the request buffer */
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- ldlm_lock2desc(lock, &body->lock_desc);
- body->lock_flags = *flags;
-
- memcpy(&body->lock_handle1, lockh, sizeof(*lockh));
- if (parent_lock_handle)
- memcpy(&body->lock_handle2, parent_lock_handle,
- sizeof(body->lock_handle2));
-
- /* Continue as normal. */
- if (!req_passed_in) {
- size = sizeof(*reply);
- req->rq_replen = lustre_msg_size(1, &size);
- }
- lock->l_connh = connh;
- lock->l_export = NULL;
-
- LDLM_DEBUG(lock, "sending request");
- rc = ptlrpc_queue_wait(req);
-
- if (rc != ELDLM_OK) {
- LASSERT(!is_replay);
- LDLM_DEBUG(lock, "client-side enqueue END (%s)",
- rc == ELDLM_LOCK_ABORTED ? "ABORTED" : "FAILED");
- ldlm_lock_decref(lockh, mode);
- /* FIXME: if we've already received a completion AST, this will
- * LBUG! */
- ldlm_lock_destroy(lock);
- GOTO(out, rc);
- }
-
- reply = lustre_msg_buf(req->rq_repmsg, 0);
- memcpy(&lock->l_remote_handle, &reply->lock_handle,
- sizeof(lock->l_remote_handle));
- *flags = reply->lock_flags;
-
- CDEBUG(D_INFO, "local: %p, remote: %p, flags: %d\n", lock,
- (void *)(unsigned long)reply->lock_handle.addr, *flags);
- if (type == LDLM_EXTENT) {
- CDEBUG(D_INFO, "requested extent: "LPU64" -> "LPU64", got "
- "extent "LPU64" -> "LPU64"\n",
- body->lock_desc.l_extent.start,
- body->lock_desc.l_extent.end,
- reply->lock_extent.start, reply->lock_extent.end);
- cookie = &reply->lock_extent; /* FIXME bug 267 */
- cookielen = sizeof(reply->lock_extent);
- }
-
- /* If enqueue returned a blocked lock but the completion handler has
- * already run, then it fixed up the resource and we don't need to do it
- * again. */
- if ((*flags) & LDLM_FL_LOCK_CHANGED) {
- int newmode = reply->lock_mode;
- LASSERT(!is_replay);
- if (newmode && newmode != lock->l_req_mode) {
- LDLM_DEBUG(lock, "server returned different mode %s",
- ldlm_lockname[newmode]);
- lock->l_req_mode = newmode;
- }
-
- if (reply->lock_resource_name[0] !=
- lock->l_resource->lr_name[0]) {
- CDEBUG(D_INFO, "remote intent success, locking %ld "
- "instead of %ld\n",
- (long)reply->lock_resource_name[0],
- (long)lock->l_resource->lr_name[0]);
-
- ldlm_lock_change_resource(lock,
- reply->lock_resource_name);
- if (lock->l_resource == NULL) {
- LBUG();
- RETURN(-ENOMEM);
- }
- LDLM_DEBUG(lock, "client-side enqueue, new resource");
- }
- }
-
- if (!is_replay) {
- rc = ldlm_lock_enqueue(lock, cookie, cookielen, flags,
- completion, blocking);
- if (lock->l_completion_ast)
- lock->l_completion_ast(lock, *flags);
- }
-
- if (!req_passed_in)
- ptlrpc_req_finished(req);
-
- LDLM_DEBUG(lock, "client-side enqueue END");
- EXIT;
- out:
- LDLM_LOCK_PUT(lock);
- out_nolock:
- return rc;
-}
-
-int ldlm_match_or_enqueue(struct lustre_handle *connh,
- struct ptlrpc_request *req,
- struct ldlm_namespace *ns,
- struct lustre_handle *parent_lock_handle,
- __u64 *res_id,
- __u32 type,
- void *cookie, int cookielen,
- ldlm_mode_t mode,
- int *flags,
- ldlm_completion_callback completion,
- ldlm_blocking_callback blocking,
- void *data,
- __u32 data_len,
- struct lustre_handle *lockh)
-{
- int rc;
- ENTRY;
- rc = ldlm_lock_match(ns, res_id, type, cookie, cookielen, mode, lockh);
- if (rc == 0) {
- rc = ldlm_cli_enqueue(connh, req, ns,
- parent_lock_handle, res_id, type, cookie,
- cookielen, mode, flags, completion,
- blocking, data, data_len, lockh);
- if (rc != ELDLM_OK)
- CERROR("ldlm_cli_enqueue: err: %d\n", rc);
- RETURN(rc);
- } else
- RETURN(0);
-}
-
-int ldlm_cli_replay_enqueue(struct ldlm_lock *lock)
-{
- struct lustre_handle lockh;
- int flags = LDLM_FL_REPLAY;
- ldlm_lock2handle(lock, &lockh);
- return ldlm_cli_enqueue(lock->l_connh, NULL, NULL, NULL, NULL,
- lock->l_resource->lr_type, NULL, 0, -1, &flags,
- NULL, NULL, NULL, 0, &lockh);
-}
-
-static int ldlm_cli_convert_local(struct ldlm_lock *lock, int new_mode,
- int *flags)
-{
- ENTRY;
- if (lock->l_resource->lr_namespace->ns_client) {
- CERROR("Trying to cancel local lock\n");
- LBUG();
- }
- LDLM_DEBUG(lock, "client-side local convert");
-
- ldlm_lock_convert(lock, new_mode, flags);
- ldlm_reprocess_all(lock->l_resource);
-
- LDLM_DEBUG(lock, "client-side local convert handler END");
- LDLM_LOCK_PUT(lock);
- RETURN(0);
-}
-
-/* FIXME: one of ldlm_cli_convert or the server side should reject attempted
- * conversion of locks which are on the waiting or converting queue */
-int ldlm_cli_convert(struct lustre_handle *lockh, int new_mode, int *flags)
-{
- struct ldlm_request *body;
- struct lustre_handle *connh;
- struct ldlm_reply *reply;
- struct ldlm_lock *lock;
- struct ldlm_resource *res;
- struct ptlrpc_request *req;
- int rc, size = sizeof(*body);
- ENTRY;
-
- lock = ldlm_handle2lock(lockh);
- if (!lock) {
- LBUG();
- RETURN(-EINVAL);
- }
- *flags = 0;
- connh = lock->l_connh;
-
- if (!connh)
- RETURN(ldlm_cli_convert_local(lock, new_mode, flags));
-
- LDLM_DEBUG(lock, "client-side convert");
-
- req = ptlrpc_prep_req(class_conn2cliimp(connh), LDLM_CONVERT, 1, &size,
- NULL);
- if (!req)
- GOTO(out, rc = -ENOMEM);
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- memcpy(&body->lock_handle1, &lock->l_remote_handle,
- sizeof(body->lock_handle1));
-
- body->lock_desc.l_req_mode = new_mode;
- body->lock_flags = *flags;
-
- size = sizeof(*reply);
- req->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(req);
- if (rc != ELDLM_OK)
- GOTO(out, rc);
-
- reply = lustre_msg_buf(req->rq_repmsg, 0);
- res = ldlm_lock_convert(lock, new_mode, &reply->lock_flags);
- if (res != NULL)
- ldlm_reprocess_all(res);
- /* Go to sleep until the lock is granted. */
- /* FIXME: or cancelled. */
- if (lock->l_completion_ast)
- lock->l_completion_ast(lock, LDLM_FL_WAIT_NOREPROC);
- EXIT;
- out:
- LDLM_LOCK_PUT(lock);
- ptlrpc_req_finished(req);
- return rc;
-}
-
-int ldlm_cli_cancel(struct lustre_handle *lockh)
-{
- struct ptlrpc_request *req;
- struct ldlm_lock *lock;
- struct ldlm_request *body;
- int rc = 0, size = sizeof(*body);
- ENTRY;
-
- /* concurrent cancels on the same handle can happen */
- lock = __ldlm_handle2lock(lockh, 0, LDLM_FL_CANCELING);
- if (lock == NULL)
- RETURN(0);
-
- if (lock->l_connh) {
- LDLM_DEBUG(lock, "client-side cancel");
- /* Set this flag to prevent others from getting new references*/
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- lock->l_flags |= LDLM_FL_CBPENDING;
- ldlm_cancel_callback(lock);
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
-
- req = ptlrpc_prep_req(class_conn2cliimp(lock->l_connh),
- LDLM_CANCEL, 1, &size, NULL);
- if (!req)
- GOTO(out, rc = -ENOMEM);
-
- /* XXX FIXME bug 249 */
- req->rq_request_portal = LDLM_CANCEL_REQUEST_PORTAL;
- req->rq_reply_portal = LDLM_CANCEL_REPLY_PORTAL;
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- memcpy(&body->lock_handle1, &lock->l_remote_handle,
- sizeof(body->lock_handle1));
-
- req->rq_replen = lustre_msg_size(0, NULL);
-
- rc = ptlrpc_queue_wait(req);
- ptlrpc_req_finished(req);
- if (rc != ELDLM_OK)
- GOTO(out, rc);
-
- ldlm_lock_cancel(lock);
- } else {
- LDLM_DEBUG(lock, "client-side local cancel");
- if (lock->l_resource->lr_namespace->ns_client) {
- CERROR("Trying to cancel local lock\n");
- LBUG();
- }
- ldlm_lock_cancel(lock);
- ldlm_reprocess_all(lock->l_resource);
- LDLM_DEBUG(lock, "client-side local cancel handler END");
- }
-
- lock->l_flags |= LDLM_FL_CANCELING;
-
- EXIT;
- out:
- LDLM_LOCK_PUT(lock);
- return rc;
-}
-
-int ldlm_cancel_lru(struct ldlm_namespace *ns)
-{
- struct list_head *tmp, *next, list = LIST_HEAD_INIT(list);
- int count, rc = 0;
- struct ldlm_ast_work *w;
- ENTRY;
-
- l_lock(&ns->ns_lock);
- count = ns->ns_nr_unused - ns->ns_max_unused;
-
- if (count <= 0) {
- l_unlock(&ns->ns_lock);
- RETURN(0);
- }
-
- list_for_each_safe(tmp, next, &ns->ns_unused_list) {
- struct ldlm_lock *lock;
- lock = list_entry(tmp, struct ldlm_lock, l_lru);
-
- LASSERT(!lock->l_readers && !lock->l_writers);
-
- /* Setting the CBPENDING flag is a little misleading, but
- * prevents an important race; namely, once CBPENDING is set,
- * the lock can accumulate no more readers/writers. Since
- * readers and writers are already zero here, ldlm_lock_decref
- * won't see this flag and call l_blocking_ast */
- lock->l_flags |= LDLM_FL_CBPENDING;
-
- OBD_ALLOC(w, sizeof(*w));
- LASSERT(w);
-
- w->w_lock = LDLM_LOCK_GET(lock);
- list_add(&w->w_list, &list);
- ldlm_lock_remove_from_lru(lock);
-
- if (--count == 0)
- break;
- }
- l_unlock(&ns->ns_lock);
-
- list_for_each_safe(tmp, next, &list) {
- struct lustre_handle lockh;
- int rc;
- w = list_entry(tmp, struct ldlm_ast_work, w_list);
-
- ldlm_lock2handle(w->w_lock, &lockh);
- rc = ldlm_cli_cancel(&lockh);
- if (rc != ELDLM_OK)
- CDEBUG(D_INFO, "ldlm_cli_cancel: %d\n", rc);
-
- list_del(&w->w_list);
- LDLM_LOCK_PUT(w->w_lock);
- OBD_FREE(w, sizeof(*w));
- }
-
- RETURN(rc);
-}
-
-int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns,
- __u64 *res_id, int flags)
-{
- struct ldlm_resource *res;
- struct list_head *tmp, *next, list = LIST_HEAD_INIT(list);
- struct ldlm_ast_work *w;
- ENTRY;
-
- res = ldlm_resource_get(ns, NULL, res_id, 0, 0);
- if (res == NULL) {
- /* This is not a problem. */
- CDEBUG(D_INFO, "No resource "LPU64"\n", res_id[0]);
- RETURN(0);
- }
-
- l_lock(&ns->ns_lock);
- list_for_each(tmp, &res->lr_granted) {
- struct ldlm_lock *lock;
- lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-
- if (lock->l_readers || lock->l_writers)
- continue;
-
- /* See CBPENDING comment in ldlm_cancel_lru */
- lock->l_flags |= LDLM_FL_CBPENDING;
-
- OBD_ALLOC(w, sizeof(*w));
- LASSERT(w);
-
- w->w_lock = LDLM_LOCK_GET(lock);
- list_add(&w->w_list, &list);
- }
- l_unlock(&ns->ns_lock);
-
- list_for_each_safe(tmp, next, &list) {
- struct lustre_handle lockh;
- int rc;
- w = list_entry(tmp, struct ldlm_ast_work, w_list);
-
- /* Prevent the cancel callback from being called by setting
- * LDLM_FL_CANCEL in the lock. Very sneaky. -p */
- if (flags & LDLM_FL_NO_CALLBACK)
- w->w_lock->l_flags |= LDLM_FL_CANCEL;
-
- if (flags & LDLM_FL_LOCAL_ONLY) {
- ldlm_lock_cancel(w->w_lock);
- } else {
- ldlm_lock2handle(w->w_lock, &lockh);
- rc = ldlm_cli_cancel(&lockh);
- if (rc != ELDLM_OK)
- CERROR("ldlm_cli_cancel: %d\n", rc);
- }
- list_del(&w->w_list);
- LDLM_LOCK_PUT(w->w_lock);
- OBD_FREE(w, sizeof(*w));
- }
-
- ldlm_resource_putref(res);
-
- RETURN(0);
-}
-
-/* Cancel all locks on a namespace (or a specific resource, if given) that have
- * 0 readers/writers.
- *
- * If 'local_only' is true, throw the locks away without trying to notify the
- * server. */
-int ldlm_cli_cancel_unused(struct ldlm_namespace *ns, __u64 *res_id,
- int flags)
-{
- int i;
- ENTRY;
-
- if (res_id)
- RETURN(ldlm_cli_cancel_unused_resource(ns, res_id, flags));
-
- l_lock(&ns->ns_lock);
- for (i = 0; i < RES_HASH_SIZE; i++) {
- struct list_head *tmp, *pos;
- list_for_each_safe(tmp, pos, &(ns->ns_hash[i])) {
- int rc;
- struct ldlm_resource *res;
- res = list_entry(tmp, struct ldlm_resource, lr_hash);
- ldlm_resource_getref(res);
-
- rc = ldlm_cli_cancel_unused_resource(ns, res->lr_name,
- flags);
-
- if (rc)
- CERROR("cancel_unused_res ("LPU64"): %d\n",
- res->lr_name[0], rc);
- ldlm_resource_putref(res);
- }
- }
- l_unlock(&ns->ns_lock);
-
- RETURN(ELDLM_OK);
-}
-
-/* Lock iterators. */
-
-int ldlm_resource_foreach(struct ldlm_resource *res, ldlm_iterator_t iter,
- void *closure)
-{
- struct list_head *tmp, *next;
- struct ldlm_lock *lock;
- int rc = LDLM_ITER_CONTINUE;
- struct ldlm_namespace *ns = res->lr_namespace;
-
- ENTRY;
-
- if (!res)
- RETURN(LDLM_ITER_CONTINUE);
-
- l_lock(&ns->ns_lock);
- list_for_each_safe(tmp, next, &res->lr_granted) {
- lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-
- if (iter(lock, closure) == LDLM_ITER_STOP)
- GOTO(out, rc = LDLM_ITER_STOP);
- }
-
- list_for_each_safe(tmp, next, &res->lr_converting) {
- lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-
- if (iter(lock, closure) == LDLM_ITER_STOP)
- GOTO(out, rc = LDLM_ITER_STOP);
- }
-
- list_for_each_safe(tmp, next, &res->lr_waiting) {
- lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-
- if (iter(lock, closure) == LDLM_ITER_STOP)
- GOTO(out, rc = LDLM_ITER_STOP);
- }
- out:
- l_unlock(&ns->ns_lock);
- RETURN(rc);
-}
-
-struct iter_helper_data {
- ldlm_iterator_t iter;
- void *closure;
-};
-
-static int ldlm_iter_helper(struct ldlm_lock *lock, void *closure)
-{
- struct iter_helper_data *helper = closure;
- return helper->iter(lock, helper->closure);
-}
-
-int ldlm_namespace_foreach(struct ldlm_namespace *ns, ldlm_iterator_t iter,
- void *closure)
-{
- int i, rc = LDLM_ITER_CONTINUE;
- struct iter_helper_data helper = { iter: iter, closure: closure };
-
- l_lock(&ns->ns_lock);
- for (i = 0; i < RES_HASH_SIZE; i++) {
- struct list_head *tmp, *next;
- list_for_each_safe(tmp, next, &(ns->ns_hash[i])) {
- struct ldlm_resource *res =
- list_entry(tmp, struct ldlm_resource, lr_hash);
-
- ldlm_resource_getref(res);
- rc = ldlm_resource_foreach(res, ldlm_iter_helper,
- &helper);
- ldlm_resource_putref(res);
- if (rc == LDLM_ITER_STOP)
- GOTO(out, rc);
- }
- }
- out:
- l_unlock(&ns->ns_lock);
- RETURN(rc);
-}
-
-/* Lock replay */
-
-static int ldlm_chain_lock_for_replay(struct ldlm_lock *lock, void *closure)
-{
- struct list_head *list = closure;
-
- /* we use l_pending_chain here, because it's unused on clients. */
- list_add(&lock->l_pending_chain, list);
- return LDLM_ITER_CONTINUE;
-}
-
-static int replay_one_lock(struct obd_import *imp, struct ldlm_lock *lock,
- int last)
-{
- struct ptlrpc_request *req;
- struct ldlm_request *body;
- struct ldlm_reply *reply;
- int rc, size;
- int flags = LDLM_FL_REPLAY;
-
- flags |= lock->l_flags &
- (LDLM_FL_BLOCK_GRANTED|LDLM_FL_BLOCK_CONV|LDLM_FL_BLOCK_WAIT);
-
- size = sizeof(*body);
- req = ptlrpc_prep_req(imp, LDLM_ENQUEUE, 1, &size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- ldlm_lock2desc(lock, &body->lock_desc);
- body->lock_flags = flags;
-
- ldlm_lock2handle(lock, &body->lock_handle1);
- size = sizeof(*reply);
- req->rq_replen = lustre_msg_size(1, &size);
-
- if (last)
- req->rq_reqmsg->flags |= MSG_LAST_REPLAY;
-
- LDLM_DEBUG(lock, "replaying lock:");
- rc = ptlrpc_queue_wait(req);
- if (rc != ELDLM_OK)
- GOTO(out, rc);
-
- reply = lustre_msg_buf(req->rq_repmsg, 0);
- memcpy(&lock->l_remote_handle, &reply->lock_handle,
- sizeof(lock->l_remote_handle));
- LDLM_DEBUG(lock, "replayed lock:");
- out:
- ptlrpc_req_finished(req);
- RETURN(rc);
-}
-
-int ldlm_replay_locks(struct obd_import *imp)
-{
- struct ldlm_namespace *ns = imp->imp_obd->obd_namespace;
- struct list_head list, *pos, *next;
- struct ldlm_lock *lock;
- int rc = 0;
-
- ENTRY;
- INIT_LIST_HEAD(&list);
-
- l_lock(&ns->ns_lock);
- (void)ldlm_namespace_foreach(ns, ldlm_chain_lock_for_replay, &list);
-
- list_for_each_safe(pos, next, &list) {
- lock = list_entry(pos, struct ldlm_lock, l_pending_chain);
- rc = replay_one_lock(imp, lock, (next == &list));
- if (rc)
- break; /* or try to do the rest? */
- }
- l_unlock(&ns->ns_lock);
- RETURN(rc);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * by Cluster File Systems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_LDLM
-
-#include <linux/lustre_dlm.h>
-#include <linux/obd_class.h>
-
-kmem_cache_t *ldlm_resource_slab, *ldlm_lock_slab;
-
-spinlock_t ldlm_namespace_lock = SPIN_LOCK_UNLOCKED;
-struct list_head ldlm_namespace_list = LIST_HEAD_INIT(ldlm_namespace_list);
-static struct proc_dir_entry *ldlm_ns_proc_dir = NULL;
-
-int ldlm_proc_setup(struct obd_device *obd)
-{
- ENTRY;
- LASSERT(ldlm_ns_proc_dir == NULL);
- ldlm_ns_proc_dir=obd->obd_type->typ_procroot;
- RETURN(0);
-}
-
-void ldlm_proc_cleanup(struct obd_device *obd)
-{
- ldlm_ns_proc_dir = NULL;
-}
-
-#define MAX_STRING_SIZE 100
-void ldlm_proc_namespace(struct ldlm_namespace *ns)
-{
- struct lprocfs_vars lock_vars[2];
- char lock_names[MAX_STRING_SIZE+1];
-
- memset(lock_vars, 0, sizeof(lock_vars));
- snprintf(lock_names, MAX_STRING_SIZE, "%s/resource_count", ns->ns_name);
- lock_names[MAX_STRING_SIZE] = '\0';
- lock_vars[0].name = lock_names;
- lock_vars[0].read_fptr = lprocfs_ll_rd;
- lock_vars[0].write_fptr = NULL;
- lock_vars[0].data = &ns->ns_resources;
- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0);
-
- memset(lock_vars, 0, sizeof(lock_vars));
- snprintf(lock_names, MAX_STRING_SIZE, "%s/lock_count", ns->ns_name);
- lock_names[MAX_STRING_SIZE] = '\0';
- lock_vars[0].name = lock_names;
- lock_vars[0].read_fptr = lprocfs_ll_rd;
- lock_vars[0].write_fptr = NULL;
- lock_vars[0].data = &ns->ns_locks;
- lprocfs_add_vars(ldlm_ns_proc_dir, lock_vars, 0);
-
-}
-#undef MAX_STRING_SIZE
-
-#define LDLM_MAX_UNUSED 20
-struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 client)
-{
- struct ldlm_namespace *ns = NULL;
- struct list_head *bucket;
- ENTRY;
-
- OBD_ALLOC(ns, sizeof(*ns));
- if (!ns) {
- LBUG();
- GOTO(out, NULL);
- }
-
- ns->ns_hash = vmalloc(sizeof(*ns->ns_hash) * RES_HASH_SIZE);
- if (!ns->ns_hash) {
- LBUG();
- GOTO(out, ns);
- }
- obd_memory += sizeof(*ns->ns_hash) * RES_HASH_SIZE;
-
- OBD_ALLOC(ns->ns_name, strlen(name) + 1);
- if (!ns->ns_name) {
- LBUG();
- GOTO(out, ns);
- }
- strcpy(ns->ns_name, name);
-
- INIT_LIST_HEAD(&ns->ns_root_list);
- l_lock_init(&ns->ns_lock);
- ns->ns_refcount = 0;
- ns->ns_client = client;
- spin_lock_init(&ns->ns_counter_lock);
- ns->ns_locks = 0;
- ns->ns_resources = 0;
-
- for (bucket = ns->ns_hash + RES_HASH_SIZE - 1; bucket >= ns->ns_hash;
- bucket--)
- INIT_LIST_HEAD(bucket);
-
- INIT_LIST_HEAD(&ns->ns_unused_list);
- ns->ns_nr_unused = 0;
- ns->ns_max_unused = LDLM_MAX_UNUSED;
-
- spin_lock(&ldlm_namespace_lock);
- list_add(&ns->ns_list_chain, &ldlm_namespace_list);
- spin_unlock(&ldlm_namespace_lock);
- ldlm_proc_namespace(ns);
- RETURN(ns);
-
- out:
- if (ns && ns->ns_hash) {
- memset(ns->ns_hash, 0x5a, sizeof(*ns->ns_hash) * RES_HASH_SIZE);
- vfree(ns->ns_hash);
- obd_memory -= sizeof(*ns->ns_hash) * RES_HASH_SIZE;
- }
- if (ns && ns->ns_name)
- OBD_FREE(ns->ns_name, strlen(name) + 1);
- if (ns)
- OBD_FREE(ns, sizeof(*ns));
- return NULL;
-}
-
-extern struct ldlm_lock *ldlm_lock_get(struct ldlm_lock *lock);
-
-/* If 'local_only' is true, don't try to tell the server, just cleanup. */
-static void cleanup_resource(struct ldlm_resource *res, struct list_head *q,
- int local_only)
-{
- struct list_head *tmp, *pos;
- int rc = 0, client = res->lr_namespace->ns_client;
- ENTRY;
-
- list_for_each_safe(tmp, pos, q) {
- struct ldlm_lock *lock;
- lock = list_entry(tmp, struct ldlm_lock, l_res_link);
- LDLM_LOCK_GET(lock);
-
- /* At shutdown time, don't call the cancellation callback */
- lock->l_flags |= LDLM_FL_CANCEL;
-
- if (client) {
- struct lustre_handle lockh;
- ldlm_lock2handle(lock, &lockh);
- if (!local_only) {
- rc = ldlm_cli_cancel(&lockh);
- if (rc)
- CERROR("ldlm_cli_cancel: %d\n", rc);
- }
- /* Force local cleanup on errors, too. */
- if (local_only || rc != ELDLM_OK)
- ldlm_lock_cancel(lock);
- } else {
- LDLM_DEBUG(lock, "Freeing a lock still held by a "
- "client node.\n");
-
- ldlm_resource_unlink_lock(lock);
- ldlm_lock_destroy(lock);
- }
- LDLM_LOCK_PUT(lock);
- }
-}
-
-int ldlm_namespace_cleanup(struct ldlm_namespace *ns, int local_only)
-{
- int i;
-
- l_lock(&ns->ns_lock);
- for (i = 0; i < RES_HASH_SIZE; i++) {
- struct list_head *tmp, *pos;
- list_for_each_safe(tmp, pos, &(ns->ns_hash[i])) {
- struct ldlm_resource *res;
- res = list_entry(tmp, struct ldlm_resource, lr_hash);
- ldlm_resource_getref(res);
-
- cleanup_resource(res, &res->lr_granted, local_only);
- cleanup_resource(res, &res->lr_converting, local_only);
- cleanup_resource(res, &res->lr_waiting, local_only);
-
- /* XXX what a mess: don't force cleanup if we're
- * local_only (which is only used by recovery). In that
- * case, we probably still have outstanding lock refs
- * which reference these resources. -phil */
- if (!ldlm_resource_putref(res) && !local_only) {
- CERROR("Resource refcount nonzero (%d) after "
- "lock cleanup; forcing cleanup.\n",
- atomic_read(&res->lr_refcount));
- ldlm_resource_dump(res);
- atomic_set(&res->lr_refcount, 1);
- ldlm_resource_putref(res);
- }
- }
- }
- l_unlock(&ns->ns_lock);
-
- return ELDLM_OK;
-}
-
-/* Cleanup, but also free, the namespace */
-int ldlm_namespace_free(struct ldlm_namespace *ns)
-{
- if (!ns)
- RETURN(ELDLM_OK);
-
- spin_lock(&ldlm_namespace_lock);
- list_del(&ns->ns_list_chain);
-
- spin_unlock(&ldlm_namespace_lock);
-
- ldlm_namespace_cleanup(ns, 0);
-
- memset(ns->ns_hash, 0x5a, sizeof(*ns->ns_hash) * RES_HASH_SIZE);
- vfree(ns->ns_hash /* , sizeof(*ns->ns_hash) * RES_HASH_SIZE */);
- obd_memory -= sizeof(*ns->ns_hash) * RES_HASH_SIZE;
- OBD_FREE(ns->ns_name, strlen(ns->ns_name) + 1);
- OBD_FREE(ns, sizeof(*ns));
-
- return ELDLM_OK;
-}
-
-int ldlm_client_free(struct obd_export *exp)
-{
- struct ldlm_export_data *led = &exp->exp_ldlm_data;
- ptlrpc_cleanup_client(&led->led_import);
- RETURN(0);
-}
-
-static __u32 ldlm_hash_fn(struct ldlm_resource *parent, __u64 *name)
-{
- __u32 hash = 0;
- int i;
-
- for (i = 0; i < RES_NAME_SIZE; i++)
- hash += name[i];
-
- hash += (__u32)((unsigned long)parent >> 4);
-
- return (hash & RES_HASH_MASK);
-}
-
-static struct ldlm_resource *ldlm_resource_new(void)
-{
- struct ldlm_resource *res;
-
- res = kmem_cache_alloc(ldlm_resource_slab, SLAB_KERNEL);
- if (res == NULL) {
- LBUG();
- return NULL;
- }
- memset(res, 0, sizeof(*res));
-
- INIT_LIST_HEAD(&res->lr_children);
- INIT_LIST_HEAD(&res->lr_childof);
- INIT_LIST_HEAD(&res->lr_granted);
- INIT_LIST_HEAD(&res->lr_converting);
- INIT_LIST_HEAD(&res->lr_waiting);
-
- atomic_set(&res->lr_refcount, 1);
-
- return res;
-}
-
-/* Args: locked namespace
- * Returns: newly-allocated, referenced, unlocked resource */
-static struct ldlm_resource *ldlm_resource_add(struct ldlm_namespace *ns,
- struct ldlm_resource *parent,
- __u64 *name, __u32 type)
-{
- struct list_head *bucket;
- struct ldlm_resource *res;
- ENTRY;
-
- if (type < LDLM_MIN_TYPE || type > LDLM_MAX_TYPE) {
- LBUG();
- RETURN(NULL);
- }
-
- res = ldlm_resource_new();
- if (!res) {
- LBUG();
- RETURN(NULL);
- }
-
- spin_lock(&ns->ns_counter_lock);
- ns->ns_resources++;
- spin_unlock(&ns->ns_counter_lock);
-
- l_lock(&ns->ns_lock);
- memcpy(res->lr_name, name, sizeof(res->lr_name));
- res->lr_namespace = ns;
- ns->ns_refcount++;
-
- res->lr_type = type;
- res->lr_most_restr = LCK_NL;
-
- bucket = ns->ns_hash + ldlm_hash_fn(parent, name);
- list_add(&res->lr_hash, bucket);
-
- if (parent == NULL) {
- list_add(&res->lr_childof, &ns->ns_root_list);
- } else {
- res->lr_parent = parent;
- list_add(&res->lr_childof, &parent->lr_children);
- }
- l_unlock(&ns->ns_lock);
-
- RETURN(res);
-}
-
-/* Args: unlocked namespace
- * Locks: takes and releases ns->ns_lock and res->lr_lock
- * Returns: referenced, unlocked ldlm_resource or NULL */
-struct ldlm_resource *ldlm_resource_get(struct ldlm_namespace *ns,
- struct ldlm_resource *parent,
- __u64 *name, __u32 type, int create)
-{
- struct list_head *bucket;
- struct list_head *tmp = bucket;
- struct ldlm_resource *res = NULL;
- ENTRY;
-
- if (ns == NULL || ns->ns_hash == NULL) {
- LBUG();
- RETURN(NULL);
- }
-
- l_lock(&ns->ns_lock);
- bucket = ns->ns_hash + ldlm_hash_fn(parent, name);
-
- list_for_each(tmp, bucket) {
- struct ldlm_resource *chk;
- chk = list_entry(tmp, struct ldlm_resource, lr_hash);
-
- if (memcmp(chk->lr_name, name, sizeof(chk->lr_name)) == 0) {
- res = chk;
- atomic_inc(&res->lr_refcount);
- l_unlock(&ns->ns_lock);
- RETURN(res);
- }
- }
-
- if (create)
- res = ldlm_resource_add(ns, parent, name, type);
- l_unlock(&ns->ns_lock);
-
- RETURN(res);
-}
-
-struct ldlm_resource *ldlm_resource_getref(struct ldlm_resource *res)
-{
- atomic_inc(&res->lr_refcount);
- CDEBUG(D_INFO, "getref res: %p count: %d\n", res,
- atomic_read(&res->lr_refcount));
- return res;
-}
-
-/* Returns 1 if the resource was freed, 0 if it remains. */
-int ldlm_resource_putref(struct ldlm_resource *res)
-{
- int rc = 0;
-
- if (atomic_dec_and_test(&res->lr_refcount)) {
- struct ldlm_namespace *ns = res->lr_namespace;
- ENTRY;
- CDEBUG(D_INFO, "putref res: %p count: %d\n", res,
- atomic_read(&res->lr_refcount));
-
- l_lock(&ns->ns_lock);
-
- if (atomic_read(&res->lr_refcount) != 0) {
- /* We lost the race. */
- l_unlock(&ns->ns_lock);
- RETURN(rc);
- }
-
- if (!list_empty(&res->lr_granted)) {
- ldlm_resource_dump(res);
- LBUG();
- }
-
- if (!list_empty(&res->lr_converting)) {
- ldlm_resource_dump(res);
- LBUG();
- }
-
- if (!list_empty(&res->lr_waiting)) {
- ldlm_resource_dump(res);
- LBUG();
- }
-
- if (!list_empty(&res->lr_children)) {
- ldlm_resource_dump(res);
- LBUG();
- }
-
- ns->ns_refcount--;
- list_del(&res->lr_hash);
- list_del(&res->lr_childof);
-
- memset(res, 0x5a, sizeof(*res));
- kmem_cache_free(ldlm_resource_slab, res);
- l_unlock(&ns->ns_lock);
-
- spin_lock(&ns->ns_counter_lock);
- ns->ns_resources--;
- spin_unlock(&ns->ns_counter_lock);
-
- rc = 1;
- } else {
- ENTRY;
- CDEBUG(D_INFO, "putref res: %p count: %d\n", res,
- atomic_read(&res->lr_refcount));
- out:
- LASSERT(atomic_read(&res->lr_refcount) >= 0);
- }
-
- RETURN(rc);
-}
-
-void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head,
- struct ldlm_lock *lock)
-{
- l_lock(&res->lr_namespace->ns_lock);
-
- ldlm_resource_dump(res);
- ldlm_lock_dump(lock);
-
- LASSERT(list_empty(&lock->l_res_link));
-
- list_add(&lock->l_res_link, head);
- l_unlock(&res->lr_namespace->ns_lock);
-}
-
-void ldlm_resource_unlink_lock(struct ldlm_lock *lock)
-{
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- list_del_init(&lock->l_res_link);
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
-}
-
-void ldlm_res2desc(struct ldlm_resource *res, struct ldlm_resource_desc *desc)
-{
- desc->lr_type = res->lr_type;
- memcpy(desc->lr_name, res->lr_name, sizeof(desc->lr_name));
- memcpy(desc->lr_version, res->lr_version, sizeof(desc->lr_version));
-}
-
-void ldlm_dump_all_namespaces(void)
-{
- struct list_head *tmp;
-
- spin_lock(&ldlm_namespace_lock);
-
- list_for_each(tmp, &ldlm_namespace_list) {
- struct ldlm_namespace *ns;
- ns = list_entry(tmp, struct ldlm_namespace, ns_list_chain);
- ldlm_namespace_dump(ns);
- }
-
- spin_unlock(&ldlm_namespace_lock);
-}
-
-void ldlm_namespace_dump(struct ldlm_namespace *ns)
-{
- struct list_head *tmp;
-
- l_lock(&ns->ns_lock);
- CDEBUG(D_OTHER, "--- Namespace: %s (rc: %d, client: %d)\n", ns->ns_name,
- ns->ns_refcount, ns->ns_client);
-
- list_for_each(tmp, &ns->ns_root_list) {
- struct ldlm_resource *res;
- res = list_entry(tmp, struct ldlm_resource, lr_childof);
-
- /* Once we have resources with children, this should really dump
- * them recursively. */
- ldlm_resource_dump(res);
- }
- l_unlock(&ns->ns_lock);
-}
-
-void ldlm_resource_dump(struct ldlm_resource *res)
-{
- struct list_head *tmp;
- char name[256];
-
- if (RES_NAME_SIZE != 3)
- LBUG();
-
- snprintf(name, sizeof(name), "%Lx %Lx %Lx",
- (unsigned long long)res->lr_name[0],
- (unsigned long long)res->lr_name[1],
- (unsigned long long)res->lr_name[2]);
-
- CDEBUG(D_OTHER, "--- Resource: %p (%s) (rc: %d)\n", res, name,
- atomic_read(&res->lr_refcount));
- CDEBUG(D_OTHER, "Namespace: %p (%s)\n", res->lr_namespace,
- res->lr_namespace->ns_name);
- CDEBUG(D_OTHER, "Parent: %p, root: %p\n", res->lr_parent, res->lr_root);
-
- CDEBUG(D_OTHER, "Granted locks:\n");
- list_for_each(tmp, &res->lr_granted) {
- struct ldlm_lock *lock;
- lock = list_entry(tmp, struct ldlm_lock, l_res_link);
- ldlm_lock_dump(lock);
- }
-
- CDEBUG(D_OTHER, "Converting locks:\n");
- list_for_each(tmp, &res->lr_converting) {
- struct ldlm_lock *lock;
- lock = list_entry(tmp, struct ldlm_lock, l_res_link);
- ldlm_lock_dump(lock);
- }
-
- CDEBUG(D_OTHER, "Waiting locks:\n");
- list_for_each(tmp, &res->lr_waiting) {
- struct ldlm_lock *lock;
- lock = list_entry(tmp, struct ldlm_lock, l_res_link);
- ldlm_lock_dump(lock);
- }
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002 Cluster File Systems, Inc. <info@clusterfs.com>
- * Copyright (c) 2002 Lawrence Livermore National Laboratory
- * Author: James Newsome <newsome2@llnl.gov>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_LDLM
-
-#include <asm/atomic.h>
-#include <linux/types.h>
-#include <linux/random.h>
-
-#include <linux/lustre_dlm.h>
-#include <linux/obd.h>
-
-struct ldlm_test_thread {
- struct obd_device *obddev;
- struct ldlm_namespace *t_ns;
- struct list_head t_link;
- __u32 t_flags;
- wait_queue_head_t t_ctl_waitq;
-};
-
-struct ldlm_test_lock {
- struct list_head l_link;
- struct lustre_handle l_lockh;
-};
-
-static unsigned int max_locks;
-static unsigned int num_resources;
-static unsigned int num_extents;
-
-static spinlock_t ctl_lock = SPIN_LOCK_UNLOCKED;
-/* protect these with the ctl_lock */
-static LIST_HEAD(ctl_threads);
-static int regression_running = 0;
-static LIST_HEAD(lock_list);
-static int num_locks = 0;
-
-/* cumulative stats for regression test */
-static atomic_t locks_requested = ATOMIC_INIT(0);
-static atomic_t converts_requested = ATOMIC_INIT(0);
-static atomic_t locks_granted = ATOMIC_INIT(0);
-static atomic_t locks_matched = ATOMIC_INIT(0);
-
-/* making this a global avoids the problem of having pointers
- * to garbage after the test exits.
- */
-static struct lustre_handle regress_connh;
-
-static int ldlm_do_decrement(void);
-static int ldlm_do_enqueue(struct ldlm_test_thread *thread);
-static int ldlm_do_convert(void);
-
-/*
- * blocking ast for regression test.
- * Just cancels lock
- */
-static int ldlm_test_blocking_ast(struct ldlm_lock *lock,
- struct ldlm_lock_desc *new,
- void *data, __u32 data_len, int flag)
-{
- int rc;
- struct lustre_handle lockh;
- ENTRY;
-
- switch (flag) {
- case LDLM_CB_BLOCKING:
- LDLM_DEBUG(lock, "We're blocking. Cancelling lock");
- ldlm_lock2handle(lock, &lockh);
- rc = ldlm_cli_cancel(&lockh);
- if (rc < 0) {
- CERROR("ldlm_cli_cancel: %d\n", rc);
- LBUG();
- }
- break;
- case LDLM_CB_CANCELING:
- LDLM_DEBUG(lock, "this lock is being cancelled");
- break;
- default:
- LBUG();
- }
-
- RETURN(0);
-}
-
-/* blocking ast for basic tests. noop */
-static int ldlm_blocking_ast(struct ldlm_lock *lock,
- struct ldlm_lock_desc *new,
- void *data, __u32 data_len, int flag)
-{
- ENTRY;
- CERROR("ldlm_blocking_ast: lock=%p, new=%p, flag=%d\n", lock, new,
- flag);
- RETURN(0);
-}
-
-/* Completion ast for regression test.
- * Does not sleep when blocked.
- */
-static int ldlm_test_completion_ast(struct ldlm_lock *lock, int flags)
-{
- struct ldlm_test_lock *lock_info;
- ENTRY;
-
- if (flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
- LDLM_FL_BLOCK_CONV)) {
- LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock");
- RETURN(0);
- }
-
- if (lock->l_granted_mode != lock->l_req_mode)
- CERROR("completion ast called with non-granted lock\n");
-
- /* add to list of granted locks */
-
- if (flags & LDLM_FL_WAIT_NOREPROC) {
- atomic_inc(&locks_matched);
- LDLM_DEBUG(lock, "lock matched");
- } else {
- atomic_inc(&locks_granted);
- LDLM_DEBUG(lock, "lock granted");
- }
-
- OBD_ALLOC(lock_info, sizeof(*lock_info));
- if (lock_info == NULL) {
- LBUG();
- RETURN(-ENOMEM);
- }
-
- ldlm_lock2handle(lock, &lock_info->l_lockh);
-
- spin_lock(&ctl_lock);
- list_add_tail(&lock_info->l_link, &lock_list);
- num_locks++;
- spin_unlock(&ctl_lock);
-
- RETURN(0);
-}
-
-int ldlm_test_basics(struct obd_device *obddev)
-{
- struct ldlm_namespace *ns;
- struct ldlm_resource *res;
- __u64 res_id[RES_NAME_SIZE] = {1, 2, 3};
- ldlm_error_t err;
- struct ldlm_lock *lock1, *lock;
- int flags;
- ENTRY;
-
- ns = ldlm_namespace_new("test_server", LDLM_NAMESPACE_SERVER);
- if (ns == NULL)
- LBUG();
-
- lock1 = ldlm_lock_create(ns, NULL, res_id, LDLM_PLAIN, LCK_CR, NULL, 0);
- if (lock1 == NULL)
- LBUG();
- err = ldlm_lock_enqueue(lock1, NULL, 0, &flags,
- ldlm_completion_ast, ldlm_blocking_ast);
- if (err != ELDLM_OK)
- LBUG();
-
- lock = ldlm_lock_create(ns, NULL, res_id, LDLM_PLAIN, LCK_EX, NULL, 0);
- if (lock == NULL)
- LBUG();
- err = ldlm_lock_enqueue(lock, NULL, 0, &flags,
- ldlm_completion_ast, ldlm_blocking_ast);
- if (err != ELDLM_OK)
- LBUG();
- if (!(flags & LDLM_FL_BLOCK_GRANTED))
- LBUG();
-
- res = ldlm_resource_get(ns, NULL, res_id, LDLM_PLAIN, 1);
- if (res == NULL)
- LBUG();
- ldlm_resource_dump(res);
-
- res = ldlm_lock_convert(lock1, LCK_NL, &flags);
- if (res != NULL)
- ldlm_reprocess_all(res);
-
- ldlm_resource_dump(res);
- ldlm_namespace_free(ns);
-
- RETURN(0);
-}
-
-int ldlm_test_extents(struct obd_device *obddev)
-{
- struct ldlm_namespace *ns;
- struct ldlm_resource *res;
- struct ldlm_lock *lock, *lock1, *lock2;
- __u64 res_id[RES_NAME_SIZE] = {0, 0, 0};
- struct ldlm_extent ext1 = {4, 6}, ext2 = {6, 9}, ext3 = {10, 11};
- ldlm_error_t err;
- int flags;
- ENTRY;
-
- ns = ldlm_namespace_new("test_server", LDLM_NAMESPACE_SERVER);
- if (ns == NULL)
- LBUG();
-
- flags = 0;
- lock1 = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_PR, NULL,
- 0);
- if (lock1 == NULL)
- LBUG();
- err = ldlm_lock_enqueue(lock1, &ext1, sizeof(ext1), &flags, NULL, NULL);
- if (err != ELDLM_OK)
- LBUG();
- if (!(flags & LDLM_FL_LOCK_CHANGED))
- LBUG();
-
- flags = 0;
- lock2 = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_PR,
- NULL, 0);
- err = ldlm_lock_enqueue(lock2, &ext2, sizeof(ext2), &flags, NULL, NULL);
- if (err != ELDLM_OK)
- LBUG();
- if (!(flags & LDLM_FL_LOCK_CHANGED))
- LBUG();
-
- flags = 0;
- lock = ldlm_lock_create(ns, NULL, res_id, LDLM_EXTENT, LCK_EX, NULL, 0);
- if (lock == NULL)
- LBUG();
- err = ldlm_lock_enqueue(lock, &ext3, sizeof(ext3), &flags,
- NULL, NULL);
- if (err != ELDLM_OK)
- LBUG();
- if (!(flags & LDLM_FL_BLOCK_GRANTED))
- LBUG();
- if (flags & LDLM_FL_LOCK_CHANGED)
- LBUG();
-
- /* Convert/cancel blocking locks */
- flags = 0;
- res = ldlm_lock_convert(lock1, LCK_NL, &flags);
- if (res != NULL)
- ldlm_reprocess_all(res);
-
- ldlm_lock_cancel(lock2);
- if (res != NULL)
- ldlm_reprocess_all(res);
-
- /* Dump the results */
- res = ldlm_resource_get(ns, NULL, res_id, LDLM_EXTENT, 0);
- if (res == NULL)
- LBUG();
- ldlm_resource_dump(res);
- ldlm_namespace_free(ns);
-
- RETURN(0);
-}
-
-static int ldlm_test_network(struct obd_device *obddev,
- struct lustre_handle *connh)
-{
-
- __u64 res_id[RES_NAME_SIZE] = {1, 2, 3};
- struct ldlm_extent ext = {4, 6};
- struct lustre_handle lockh1;
- struct ldlm_lock *lock;
- int flags = 0;
- ldlm_error_t err;
- ENTRY;
-
- err = ldlm_cli_enqueue(connh, NULL, obddev->obd_namespace, NULL, res_id,
- LDLM_EXTENT, &ext, sizeof(ext), LCK_PR, &flags,
- ldlm_completion_ast, NULL, NULL, 0, &lockh1);
-
- CERROR("ldlm_cli_enqueue: %d\n", err);
-
- flags = 0;
- err = ldlm_cli_convert(&lockh1, LCK_EX, &flags);
- CERROR("ldlm_cli_convert: %d\n", err);
-
- lock = ldlm_handle2lock(&lockh1);
- ldlm_lock_dump(lock);
- ldlm_lock_put(lock);
-
- /* Need to decrement old mode. Don't bother incrementing new
- * mode since the test is done.
- */
- if (err == ELDLM_OK)
- ldlm_lock_decref(&lockh1, LCK_PR);
-
- RETURN(err);
-}
-
-static int ldlm_do_decrement(void)
-{
- struct ldlm_test_lock *lock_info;
- struct ldlm_lock *lock;
- int rc = 0;
- ENTRY;
-
- spin_lock(&ctl_lock);
- if(list_empty(&lock_list)) {
- CERROR("lock_list is empty\n");
- spin_unlock(&ctl_lock);
- RETURN(0);
- }
-
- /* delete from list */
- lock_info = list_entry(lock_list.next,
- struct ldlm_test_lock, l_link);
- list_del(lock_list.next);
- num_locks--;
- spin_unlock(&ctl_lock);
-
- /* decrement and free the info */
- lock = ldlm_handle2lock(&lock_info->l_lockh);
- ldlm_lock_decref(&lock_info->l_lockh, lock->l_granted_mode);
- ldlm_lock_put(lock);
-
- OBD_FREE(lock_info, sizeof(*lock_info));
-
- RETURN(rc);
-}
-
-static int ldlm_do_enqueue(struct ldlm_test_thread *thread)
-{
- struct lustre_handle lockh;
- __u64 res_id[3] = {0};
- __u32 lock_mode;
- struct ldlm_extent ext;
- unsigned char random;
- int flags = 0, rc = 0;
- ENTRY;
-
- /* Pick a random resource from 1 to num_resources */
- get_random_bytes(&random, sizeof(random));
- res_id[0] = random % num_resources;
-
- /* Pick a random lock mode */
- get_random_bytes(&random, sizeof(random));
- lock_mode = random % LCK_NL + 1;
-
- /* Pick a random extent */
- get_random_bytes(&random, sizeof(random));
- ext.start = random % num_extents;
- get_random_bytes(&random, sizeof(random));
- ext.end = random %
- (num_extents - (int)ext.start) + ext.start;
-
- LDLM_DEBUG_NOLOCK("about to enqueue with resource "LPX64", mode %d,"
- " extent "LPX64" -> "LPX64, res_id[0], lock_mode,
- ext.start, ext.end);
-
- rc = ldlm_match_or_enqueue(®ress_connh, NULL,
- thread->obddev->obd_namespace,
- NULL, res_id, LDLM_EXTENT, &ext,
- sizeof(ext), lock_mode, &flags,
- ldlm_test_completion_ast,
- ldlm_test_blocking_ast,
- NULL, 0, &lockh);
-
- atomic_inc(&locks_requested);
-
- if (rc < 0) {
- CERROR("ldlm_cli_enqueue: %d\n", rc);
- LBUG();
- }
-
- RETURN(rc);
-}
-
-static int ldlm_do_convert(void)
-{
- __u32 lock_mode;
- unsigned char random;
- int flags = 0, rc = 0;
- struct ldlm_test_lock *lock_info;
- struct ldlm_lock *lock;
- ENTRY;
-
- /* delete from list */
- spin_lock(&ctl_lock);
- lock_info = list_entry(lock_list.next, struct ldlm_test_lock, l_link);
- list_del(lock_list.next);
- num_locks--;
- spin_unlock(&ctl_lock);
-
- /* Pick a random lock mode */
- get_random_bytes(&random, sizeof(random));
- lock_mode = random % LCK_NL + 1;
-
- /* do the conversion */
- rc = ldlm_cli_convert(&lock_info->l_lockh , lock_mode, &flags);
- atomic_inc(&converts_requested);
-
- if (rc < 0) {
- CERROR("ldlm_cli_convert: %d\n", rc);
- LBUG();
- }
-
- /*
- * Adjust reference counts.
- * FIXME: This is technically a bit... wrong,
- * since we don't know when/if the convert succeeded
- */
- ldlm_lock_addref(&lock_info->l_lockh, lock_mode);
- lock = ldlm_handle2lock(&lock_info->l_lockh);
- ldlm_lock_decref(&lock_info->l_lockh, lock->l_granted_mode);
- ldlm_lock_put(lock);
-
- OBD_FREE(lock_info, sizeof(*lock_info));
-
- RETURN(rc);
-}
-
-
-
-static int ldlm_test_main(void *data)
-{
- struct ldlm_test_thread *thread = data;
- ENTRY;
-
- lock_kernel();
- daemonize();
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- sigfillset(¤t->blocked);
- recalc_sigpending();
-#else
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
-#endif
-
- sprintf(current->comm, "ldlm_test");
- unlock_kernel();
-
- /* Record that the thread is running */
- thread->t_flags |= SVC_RUNNING;
- wake_up(&thread->t_ctl_waitq);
-
- while (!(thread->t_flags & SVC_STOPPING)) {
- unsigned char random;
- unsigned char dec_chance, con_chance;
- unsigned char chance_left = 100;
-
- spin_lock(&ctl_lock);
- /* probability of decrementing increases linearly
- * as more locks are held.
- */
- dec_chance = chance_left * num_locks / max_locks;
- chance_left -= dec_chance;
-
- /* FIXME: conversions temporarily disabled
- * until they are working correctly.
- */
- /* con_chance = chance_left * num_locks / max_locks; */
- con_chance = 0;
- chance_left -= con_chance;
- spin_unlock(&ctl_lock);
-
- get_random_bytes(&random, sizeof(random));
-
- random = random % 100;
- if (random < dec_chance)
- ldlm_do_decrement();
- else if (random < (dec_chance + con_chance))
- ldlm_do_convert();
- else
- ldlm_do_enqueue(thread);
-
- LDLM_DEBUG_NOLOCK("locks requested: %d, "
- "conversions requested %d",
- atomic_read(&locks_requested),
- atomic_read(&converts_requested));
- LDLM_DEBUG_NOLOCK("locks granted: %d, "
- "locks matched: %d",
- atomic_read(&locks_granted),
- atomic_read(&locks_matched));
-
- spin_lock(&ctl_lock);
- LDLM_DEBUG_NOLOCK("lock references currently held: %d, ",
- num_locks);
- spin_unlock(&ctl_lock);
-
- /*
- * We don't sleep after a lock being blocked, so let's
- * make sure other things can run.
- */
- schedule();
- }
-
- thread->t_flags |= SVC_STOPPED;
- wake_up(&thread->t_ctl_waitq);
-
- RETURN(0);
-}
-
-static int ldlm_start_thread(struct obd_device *obddev,
- struct lustre_handle *connh)
-{
- struct ldlm_test_thread *test;
- int rc;
- ENTRY;
-
- OBD_ALLOC(test, sizeof(*test));
- if (test == NULL) {
- LBUG();
- RETURN(-ENOMEM);
- }
- init_waitqueue_head(&test->t_ctl_waitq);
-
- test->obddev = obddev;
-
- spin_lock(&ctl_lock);
- list_add(&test->t_link, &ctl_threads);
- spin_unlock(&ctl_lock);
-
- rc = kernel_thread(ldlm_test_main, (void *)test,
- CLONE_VM | CLONE_FS | CLONE_FILES);
- if (rc < 0) {
- CERROR("cannot start thread\n");
- RETURN(-EINVAL);
- }
- wait_event(test->t_ctl_waitq, test->t_flags & SVC_RUNNING);
-
- RETURN(0);
-}
-
-int ldlm_regression_start(struct obd_device *obddev,
- struct lustre_handle *connh,
- unsigned int threads, unsigned int max_locks_in,
- unsigned int num_resources_in,
- unsigned int num_extents_in)
-{
- int i, rc = 0;
- ENTRY;
-
- spin_lock(&ctl_lock);
- if (regression_running) {
- CERROR("You can't start the ldlm regression twice.\n");
- spin_unlock(&ctl_lock);
- RETURN(-EINVAL);
- }
- regression_running = 1;
- spin_unlock(&ctl_lock);
-
- regress_connh = *connh;
- max_locks = max_locks_in;
- num_resources = num_resources_in;
- num_extents = num_extents_in;
-
- LDLM_DEBUG_NOLOCK("regression test started: threads: %d, max_locks: "
- "%d, num_res: %d, num_ext: %d\n",
- threads, max_locks_in, num_resources_in,
- num_extents_in);
-
- for (i = 0; i < threads; i++) {
- rc = ldlm_start_thread(obddev, connh);
- if (rc < 0)
- GOTO(cleanup, rc);
- }
-
- cleanup:
- if (rc < 0)
- ldlm_regression_stop();
- RETURN(rc);
-}
-
-int ldlm_regression_stop(void)
-{
- ENTRY;
-
- spin_lock(&ctl_lock);
- if (!regression_running) {
- CERROR("The ldlm regression isn't started.\n");
- spin_unlock(&ctl_lock);
- RETURN(-EINVAL);
- }
-
- while (!list_empty(&ctl_threads)) {
- struct ldlm_test_thread *thread;
- thread = list_entry(ctl_threads.next, struct ldlm_test_thread,
- t_link);
-
- thread->t_flags |= SVC_STOPPING;
-
- spin_unlock(&ctl_lock);
- wake_up(&thread->t_ctl_waitq);
- wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_STOPPED);
- spin_lock(&ctl_lock);
-
- list_del(&thread->t_link);
- OBD_FREE(thread, sizeof(*thread));
- }
-
- /* decrement all held locks */
- while (!list_empty(&lock_list)) {
- struct ldlm_lock *lock;
- struct ldlm_test_lock *lock_info =
- list_entry(lock_list.next, struct ldlm_test_lock,
- l_link);
- list_del(lock_list.next);
- num_locks--;
-
- lock = ldlm_handle2lock(&lock_info->l_lockh);
- ldlm_lock_decref(&lock_info->l_lockh, lock->l_granted_mode);
- ldlm_lock_put(lock);
-
- OBD_FREE(lock_info, sizeof(*lock_info));
- }
-
- regression_running = 0;
- spin_unlock(&ctl_lock);
-
- RETURN(0);
-}
-
-int ldlm_test(struct obd_device *obddev, struct lustre_handle *connh)
-{
- int rc;
- rc = ldlm_test_basics(obddev);
- if (rc)
- RETURN(rc);
-
- rc = ldlm_test_extents(obddev);
- if (rc)
- RETURN(rc);
-
- rc = ldlm_test_network(obddev, connh);
- RETURN(rc);
-}
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
-EXTRA_DIST = mds_updates.c obd_pack.c ll_pack.c simple.c
-EXTRA_DIST += client.c target.c
-
-include $(top_srcdir)/Rules
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- * Author: Peter J. Braam <braam@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- * Author: Mike Shaver <shaver@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Client-common OBD method implementations and utility functions.
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_OST /* XXX WRONG */
-
-#include <linux/module.h>
-#include <linux/obd_ost.h>
-#include <linux/lustre_net.h>
-#include <linux/lustre_dlm.h>
-
-struct client_obd *client_conn2cli(struct lustre_handle *conn)
-{
- struct obd_export *export = class_conn2export(conn);
- if (!export)
- LBUG();
- return &export->exp_obd->u.cli;
-}
-
-int client_obd_setup(struct obd_device *obddev, obd_count len, void *buf)
-{
- struct obd_ioctl_data* data = buf;
- int rq_portal, rp_portal;
- char *name;
- struct client_obd *cli = &obddev->u.cli;
- struct obd_import *imp = &cli->cl_import;
- obd_uuid_t server_uuid;
- ENTRY;
-
- if (obddev->obd_type->typ_ops->o_brw) {
- rq_portal = OST_REQUEST_PORTAL;
- rp_portal = OSC_REPLY_PORTAL;
- name = "osc";
- } else {
- rq_portal = MDS_REQUEST_PORTAL;
- rp_portal = MDC_REPLY_PORTAL;
- name = "mdc";
- }
-
- if (data->ioc_inllen1 < 1) {
- CERROR("requires a TARGET UUID\n");
- RETURN(-EINVAL);
- }
-
- if (data->ioc_inllen1 > 37) {
- CERROR("client UUID must be less than 38 characters\n");
- RETURN(-EINVAL);
- }
-
- if (data->ioc_inllen2 < 1) {
- CERROR("setup requires a SERVER UUID\n");
- RETURN(-EINVAL);
- }
-
- if (data->ioc_inllen2 > 37) {
- CERROR("target UUID must be less than 38 characters\n");
- RETURN(-EINVAL);
- }
-
- sema_init(&cli->cl_sem, 1);
- cli->cl_conn_count = 0;
- memcpy(cli->cl_target_uuid, data->ioc_inlbuf1, data->ioc_inllen1);
- memcpy(server_uuid, data->ioc_inlbuf2, MIN(data->ioc_inllen2,
- sizeof(server_uuid)));
-
- imp->imp_connection = ptlrpc_uuid_to_connection(server_uuid);
- if (!imp->imp_connection)
- RETURN(-ENOENT);
-
- INIT_LIST_HEAD(&imp->imp_replay_list);
- INIT_LIST_HEAD(&imp->imp_sending_list);
- INIT_LIST_HEAD(&imp->imp_delayed_list);
- spin_lock_init(&imp->imp_lock);
-
- ptlrpc_init_client(rq_portal, rp_portal, name,
- &obddev->obd_ldlm_client);
- imp->imp_client = &obddev->obd_ldlm_client;
- imp->imp_obd = obddev;
-
- cli->cl_max_mds_easize = sizeof(struct lov_mds_md);
-
- MOD_INC_USE_COUNT;
- RETURN(0);
-}
-
-int client_obd_cleanup(struct obd_device * obddev)
-{
- struct client_obd *obd = &obddev->u.cli;
-
- ptlrpc_cleanup_client(&obd->cl_import);
- ptlrpc_put_connection(obd->cl_import.imp_connection);
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-int client_obd_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- struct client_obd *cli = &obd->u.cli;
- struct ptlrpc_request *request;
- int rc, size[] = {sizeof(cli->cl_target_uuid),
- sizeof(obd->obd_uuid) };
- char *tmp[] = {cli->cl_target_uuid, obd->obd_uuid};
- int rq_opc = (obd->obd_type->typ_ops->o_brw) ? OST_CONNECT :MDS_CONNECT;
- struct ptlrpc_connection *c;
- struct obd_import *imp = &cli->cl_import;
-
- ENTRY;
- down(&cli->cl_sem);
- MOD_INC_USE_COUNT;
- rc = class_connect(conn, obd, cluuid);
- if (rc) {
- MOD_DEC_USE_COUNT;
- GOTO(out_sem, rc);
- }
- cli->cl_conn_count++;
- if (cli->cl_conn_count > 1)
- GOTO(out_sem, rc);
-
- if (obd->obd_namespace != NULL)
- CERROR("already have namespace!\n");
- obd->obd_namespace = ldlm_namespace_new(obd->obd_name,
- LDLM_NAMESPACE_CLIENT);
- if (obd->obd_namespace == NULL)
- GOTO(out_disco, rc = -ENOMEM);
-
- INIT_LIST_HEAD(&imp->imp_chain);
- imp->imp_last_xid = 0;
- imp->imp_max_transno = 0;
- imp->imp_peer_last_xid = 0;
- imp->imp_peer_committed_transno = 0;
-
- request = ptlrpc_prep_req(&cli->cl_import, rq_opc, 2, size, tmp);
- if (!request)
- GOTO(out_ldlm, rc = -ENOMEM);
-
- request->rq_level = LUSTRE_CONN_NEW;
- request->rq_replen = lustre_msg_size(0, NULL);
- request->rq_reqmsg->addr = conn->addr;
- request->rq_reqmsg->cookie = conn->cookie;
- c = class_conn2export(conn)->exp_connection =
- ptlrpc_connection_addref(request->rq_connection);
- list_add(&imp->imp_chain, &c->c_imports);
- recovd_conn_manage(c, recovd, recover);
-
- imp->imp_level = LUSTRE_CONN_CON;
- rc = ptlrpc_queue_wait(request);
- if (rc)
- GOTO(out_req, rc);
-
- if (rq_opc == MDS_CONNECT)
- imp->imp_flags |= IMP_REPLAYABLE;
- imp->imp_level = LUSTRE_CONN_FULL;
- imp->imp_handle.addr = request->rq_repmsg->addr;
- imp->imp_handle.cookie = request->rq_repmsg->cookie;
-
- EXIT;
-out_req:
- ptlrpc_req_finished(request);
- if (rc) {
-out_ldlm:
- ldlm_namespace_free(obd->obd_namespace);
- obd->obd_namespace = NULL;
- if (rq_opc == MDS_CONNECT) {
- /* Don't class_disconnect OSCs, because the LOV
- * cares about them even if they can't connect to the
- * OST.
- *
- * This is leak-bait, but without either a way to
- * operate on the osc without an export or separate
- * methods for connect-to-osc and connect-osc-to-ost
- * it's not clear what else to do.
- */
-out_disco:
- cli->cl_conn_count--;
- class_disconnect(conn);
- MOD_DEC_USE_COUNT;
- }
- }
-out_sem:
- up(&cli->cl_sem);
- return rc;
-}
-
-int client_obd_disconnect(struct lustre_handle *conn)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct client_obd *cli = &obd->u.cli;
- int rq_opc;
- struct ptlrpc_request *request = NULL;
- int rc, err;
- ENTRY;
-
- if (!obd) {
- CERROR("invalid connection for disconnect: addr "LPX64
- ", cookie "LPX64"\n", conn ? conn->addr : -1UL,
- conn ? conn->cookie : -1UL);
- RETURN(-EINVAL);
- }
-
- rq_opc = obd->obd_type->typ_ops->o_brw ? OST_DISCONNECT:MDS_DISCONNECT;
- down(&cli->cl_sem);
- if (!cli->cl_conn_count) {
- CERROR("disconnecting disconnected device (%s)\n",
- obd->obd_name);
- GOTO(out_sem, rc = -EINVAL);
- }
-
- cli->cl_conn_count--;
- if (cli->cl_conn_count)
- GOTO(out_disco, rc = 0);
-
- ldlm_namespace_free(obd->obd_namespace);
- obd->obd_namespace = NULL;
- request = ptlrpc_prep_req(&cli->cl_import, rq_opc, 0, NULL,
- NULL);
- if (!request)
- GOTO(out_disco, rc = -ENOMEM);
-
- request->rq_replen = lustre_msg_size(0, NULL);
-
- /* Process disconnects even if we're waiting for recovery. */
- request->rq_level = LUSTRE_CONN_RECOVD;
-
- rc = ptlrpc_queue_wait(request);
- if (rc)
- GOTO(out_req, rc);
-
- EXIT;
- out_req:
- if (request)
- ptlrpc_req_finished(request);
- out_disco:
- err = class_disconnect(conn);
- if (!rc && err)
- rc = err;
- list_del_init(&cli->cl_import.imp_chain);
- MOD_DEC_USE_COUNT;
- out_sem:
- up(&cli->cl_sem);
- RETURN(rc);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc. <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * (Un)packing of OST/MDS requests
- *
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_net.h>
-#include <linux/obd_support.h>
-
-void obd_statfs_pack(struct obd_statfs *tgt, struct obd_statfs *src)
-{
- tgt->os_type = HTON__u64(src->os_type);
- tgt->os_blocks = HTON__u64(src->os_blocks);
- tgt->os_bfree = HTON__u64(src->os_bfree);
- tgt->os_bavail = HTON__u64(src->os_bavail);
- tgt->os_files = HTON__u64(src->os_files);
- tgt->os_ffree = HTON__u64(src->os_ffree);
- tgt->os_bsize = HTON__u32(src->os_bsize);
- tgt->os_namelen = HTON__u32(src->os_namelen);
-}
-
-#define obd_statfs_unpack(tgt, src) obd_statfs_pack(tgt, src)
-
-void statfs_pack(struct obd_statfs *osfs, struct statfs *sfs)
-{
- osfs->os_type = sfs->f_type;
- osfs->os_blocks = sfs->f_blocks;
- osfs->os_bfree = sfs->f_bfree;
- osfs->os_bavail = sfs->f_bavail;
- osfs->os_files = sfs->f_files;
- osfs->os_ffree = sfs->f_ffree;
- osfs->os_bsize = sfs->f_bsize;
- osfs->os_namelen = sfs->f_namelen;
-}
-
-void statfs_unpack(struct statfs *sfs, struct obd_statfs *osfs)
-{
- sfs->f_type = osfs->os_type;
- sfs->f_blocks = osfs->os_blocks;
- sfs->f_bfree = osfs->os_bfree;
- sfs->f_bavail = osfs->os_bavail;
- sfs->f_files = osfs->os_files;
- sfs->f_ffree = osfs->os_ffree;
- sfs->f_bsize = osfs->os_bsize;
- sfs->f_namelen = osfs->os_namelen;
-}
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copryright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.sf.net/projects/lustre/
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Lustre Lite Update Records
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#include <linux/locks.h> // for wait_on_buffer
-#else
-#include <linux/buffer_head.h> // for wait_on_buffer
-#endif
-#include <linux/unistd.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
-#include <linux/slab.h>
-#include <asm/segment.h>
-
-#define DEBUG_SUBSYSTEM S_MDS
-
-#include <linux/obd_support.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_lite.h>
-
-void mds_pack_inode2fid(struct ll_fid *fid, struct inode *inode)
-{
- fid->id = HTON__u64(inode->i_ino);
- fid->generation = HTON__u32(inode->i_generation);
- fid->f_type = HTON__u32(S_IFMT & inode->i_mode);
-}
-
-
-void mds_pack_inode2body(struct mds_body *b, struct inode *inode)
-{
- b->valid = OBD_MD_FLID | OBD_MD_FLATIME | OBD_MD_FLMTIME |
- OBD_MD_FLCTIME | OBD_MD_FLSIZE | OBD_MD_FLUID | OBD_MD_FLGID |
- OBD_MD_FLTYPE | OBD_MD_FLMODE | OBD_MD_FLNLINK | OBD_MD_FLGENER;
- b->ino = HTON__u32(inode->i_ino);
- b->atime = HTON__u32(inode->i_atime);
- b->mtime = HTON__u32(inode->i_mtime);
- b->ctime = HTON__u32(inode->i_ctime);
- b->mode = HTON__u32(inode->i_mode);
- b->size = HTON__u64(inode->i_size);
- b->uid = HTON__u32(inode->i_uid);
- b->gid = HTON__u32(inode->i_gid);
- b->flags = HTON__u32(inode->i_flags);
- b->rdev = HTON__u32(b->rdev);
- b->nlink = HTON__u32(inode->i_nlink);
- b->generation = HTON__u32(inode->i_generation);
-}
-
-
-void mds_pack_fid(struct ll_fid *fid)
-{
- fid->id = HTON__u64(fid->id);
- fid->generation = HTON__u32(fid->generation);
- fid->f_type = HTON__u32(fid->f_type);
-}
-
-static void mds_pack_body(struct mds_body *b)
-{
- if (b == NULL)
- LBUG();
-
- b->fsuid = HTON__u32(current->fsuid);
- b->fsgid = HTON__u32(current->fsgid);
- b->capability = HTON__u32(current->cap_effective);
-
- mds_pack_fid(&b->fid1);
- mds_pack_fid(&b->fid2);
- b->size = HTON__u64(b->size);
- b->ino = HTON__u32(b->ino);
- b->valid = HTON__u32(b->valid);
- b->mode = HTON__u32(b->mode);
- b->uid = HTON__u32(b->uid);
- b->gid = HTON__u32(b->gid);
- b->mtime = HTON__u32(b->mtime);
- b->ctime = HTON__u32(b->ctime);
- b->atime = HTON__u32(b->atime);
- b->flags = HTON__u32(b->flags);
- b->rdev = HTON__u32(b->rdev);
- b->nlink = HTON__u32(b->nlink);
- b->generation = HTON__u32(b->generation);
-}
-
-void mds_getattr_pack(struct ptlrpc_request *req, int offset,
- struct inode *inode,
- const char *name, int namelen)
-{
- struct mds_body *b;
- b = lustre_msg_buf(req->rq_reqmsg, offset);
-
- b->fsuid = HTON__u32(current->fsuid);
- b->fsgid = HTON__u32(current->fsgid);
- b->capability = HTON__u32(current->cap_effective);
-
- ll_inode2fid(&b->fid1, inode);
- if (name) {
- char *tmp;
- tmp = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- LOGL0(name, namelen, tmp);
- }
-}
-
-void mds_readdir_pack(struct ptlrpc_request *req, __u64 offset,
- obd_id ino, int type)
-{
- struct mds_body *b;
-
- b = lustre_msg_buf(req->rq_reqmsg, 0);
- b->fsuid = HTON__u32(current->fsuid);
- b->fsgid = HTON__u32(current->fsgid);
- b->capability = HTON__u32(current->cap_effective);
- b->fid1.id = HTON__u64(ino);
- b->fid1.f_type = HTON__u32(type);
- b->size = HTON__u64(offset);
-}
-
-
-void mds_pack_req_body(struct ptlrpc_request *req)
-{
- struct mds_body *b = lustre_msg_buf(req->rq_reqmsg, 0);
- mds_pack_body(b);
-}
-
-void mds_pack_rep_body(struct ptlrpc_request *req)
-{
- struct mds_body *b = lustre_msg_buf(req->rq_repmsg, 0);
- mds_pack_body(b);
-}
-
-
-/* packing of MDS records */
-void mds_create_pack(struct ptlrpc_request *req, int offset, struct inode *dir,
- __u32 mode, __u64 rdev, __u32 uid, __u32 gid, __u64 time,
- const char *name, int namelen,
- const void *data, int datalen)
-{
- struct mds_rec_create *rec;
- char *tmp;
- rec = lustre_msg_buf(req->rq_reqmsg, offset);
-
- /* XXX do something about time, uid, gid */
- rec->cr_opcode = HTON__u32(REINT_CREATE);
- rec->cr_fsuid = HTON__u32(current->fsuid);
- rec->cr_fsgid = HTON__u32(current->fsgid);
- rec->cr_cap = HTON__u32(current->cap_effective);
- ll_inode2fid(&rec->cr_fid, dir);
- memset(&rec->cr_replayfid, 0, sizeof(rec->cr_replayfid));
- rec->cr_mode = HTON__u32(mode);
- rec->cr_rdev = HTON__u64(rdev);
- rec->cr_uid = HTON__u32(uid);
- rec->cr_gid = HTON__u32(gid);
- rec->cr_time = HTON__u64(time);
-
- tmp = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- LOGL0(name, namelen, tmp);
-
- if (data) {
- tmp = lustre_msg_buf(req->rq_reqmsg, offset + 2);
- LOGL0(data, datalen, tmp);
- }
-}
-
-void mds_setattr_pack(struct ptlrpc_request *req, int offset,
- struct inode *inode, struct iattr *iattr,
- const char *name, int namelen)
-{
- struct mds_rec_setattr *rec;
- rec = lustre_msg_buf(req->rq_reqmsg, offset);
-
- rec->sa_opcode = HTON__u32(REINT_SETATTR);
- rec->sa_fsuid = HTON__u32(current->fsuid);
- rec->sa_fsgid = HTON__u32(current->fsgid);
- rec->sa_cap = HTON__u32(current->cap_effective);
- ll_inode2fid(&rec->sa_fid, inode);
- rec->sa_valid = HTON__u32(iattr->ia_valid);
- rec->sa_mode = HTON__u32(iattr->ia_mode);
- rec->sa_uid = HTON__u32(iattr->ia_uid);
- rec->sa_gid = HTON__u32(iattr->ia_gid);
- rec->sa_size = HTON__u64(iattr->ia_size);
- rec->sa_atime = HTON__u64(iattr->ia_atime);
- rec->sa_mtime = HTON__u64(iattr->ia_mtime);
- rec->sa_ctime = HTON__u64(iattr->ia_ctime);
- rec->sa_attr_flags = HTON__u32(iattr->ia_attr_flags);
-
- if (namelen) {
- char *tmp;
- tmp = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- LOGL0(name, namelen, tmp);
- }
-}
-
-void mds_unlink_pack(struct ptlrpc_request *req, int offset,
- struct inode *inode, struct inode *child, __u32 mode,
- const char *name, int namelen)
-{
- struct mds_rec_unlink *rec;
- char *tmp;
-
- rec = lustre_msg_buf(req->rq_reqmsg, offset);
-
- rec->ul_opcode = HTON__u32(REINT_UNLINK);
- rec->ul_fsuid = HTON__u32(current->fsuid);
- rec->ul_fsgid = HTON__u32(current->fsgid);
- rec->ul_cap = HTON__u32(current->cap_effective);
- rec->ul_mode = HTON__u32(mode);
- ll_inode2fid(&rec->ul_fid1, inode);
- if (child)
- ll_inode2fid(&rec->ul_fid2, child);
-
- tmp = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- LOGL0(name, namelen, tmp);
-}
-
-void mds_link_pack(struct ptlrpc_request *req, int offset,
- struct inode *inode, struct inode *dir,
- const char *name, int namelen)
-{
- struct mds_rec_link *rec;
- char *tmp;
-
- rec = lustre_msg_buf(req->rq_reqmsg, offset);
-
- rec->lk_opcode = HTON__u32(REINT_LINK);
- rec->lk_fsuid = HTON__u32(current->fsuid);
- rec->lk_fsgid = HTON__u32(current->fsgid);
- rec->lk_cap = HTON__u32(current->cap_effective);
- ll_inode2fid(&rec->lk_fid1, inode);
- ll_inode2fid(&rec->lk_fid2, dir);
-
- tmp = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- LOGL0(name, namelen, tmp);
-}
-
-void mds_rename_pack(struct ptlrpc_request *req, int offset,
- struct inode *srcdir, struct inode *tgtdir,
- const char *old, int oldlen, const char *new, int newlen)
-{
- struct mds_rec_rename *rec;
- char *tmp;
-
- rec = lustre_msg_buf(req->rq_reqmsg, offset);
-
- /* XXX do something about time, uid, gid */
- rec->rn_opcode = HTON__u32(REINT_RENAME);
- rec->rn_fsuid = HTON__u32(current->fsuid);
- rec->rn_fsgid = HTON__u32(current->fsgid);
- rec->rn_cap = HTON__u32(current->cap_effective);
- ll_inode2fid(&rec->rn_fid1, srcdir);
- ll_inode2fid(&rec->rn_fid2, tgtdir);
-
- tmp = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- LOGL0(old, oldlen, tmp);
-
- if (new) {
- tmp = lustre_msg_buf(req->rq_reqmsg, offset + 2);
- LOGL0(new, newlen, tmp);
- }
-}
-
-/* unpacking */
-void mds_unpack_fid(struct ll_fid *fid)
-{
- fid->id = NTOH__u64(fid->id);
- fid->generation = NTOH__u32(fid->generation);
- fid->f_type = NTOH__u32(fid->f_type);
-}
-
-void mds_unpack_body(struct mds_body *b)
-{
- if (b == NULL)
- LBUG();
-
- mds_unpack_fid(&b->fid1);
- mds_unpack_fid(&b->fid2);
- b->size = NTOH__u64(b->size);
- b->valid = NTOH__u32(b->valid);
- b->fsuid = NTOH__u32(b->fsuid);
- b->fsgid = NTOH__u32(b->fsgid);
- b->capability = NTOH__u32(b->capability);
- b->ino = NTOH__u32(b->ino);
- b->mode = NTOH__u32(b->mode);
- b->uid = NTOH__u32(b->uid);
- b->gid = NTOH__u32(b->gid);
- b->mtime = NTOH__u32(b->mtime);
- b->ctime = NTOH__u32(b->ctime);
- b->atime = NTOH__u32(b->atime);
- b->flags = NTOH__u32(b->flags);
- b->rdev = NTOH__u32(b->rdev);
- b->nlink = NTOH__u32(b->nlink);
- b->generation = NTOH__u32(b->generation);
-}
-
-static int mds_setattr_unpack(struct ptlrpc_request *req, int offset,
- struct mds_update_record *r)
-{
- struct iattr *attr = &r->ur_iattr;
- struct mds_rec_setattr *rec = lustre_msg_buf(req->rq_reqmsg, offset);
- ENTRY;
-
- if (req->rq_reqmsg->bufcount < offset + 1 ||
- req->rq_reqmsg->buflens[offset] != sizeof(*rec))
- RETURN(-EFAULT);
-
- r->ur_fsuid = NTOH__u32(rec->sa_fsuid);
- r->ur_fsgid = NTOH__u32(rec->sa_fsgid);
- r->ur_cap = NTOH__u32(rec->sa_cap);
- r->ur_fid1 = &rec->sa_fid;
- attr->ia_valid = NTOH__u32(rec->sa_valid);
- attr->ia_mode = NTOH__u32(rec->sa_mode);
- attr->ia_uid = NTOH__u32(rec->sa_uid);
- attr->ia_gid = NTOH__u32(rec->sa_gid);
- attr->ia_size = NTOH__u64(rec->sa_size);
- attr->ia_atime = NTOH__u64(rec->sa_atime);
- attr->ia_mtime = NTOH__u64(rec->sa_mtime);
- attr->ia_ctime = NTOH__u64(rec->sa_ctime);
- attr->ia_attr_flags = NTOH__u32(rec->sa_attr_flags);
-
- if (req->rq_reqmsg->bufcount == offset + 2) {
- r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
- r->ur_name = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- } else
- r->ur_namelen = 0;
-
- RETURN(0);
-}
-
-static int mds_create_unpack(struct ptlrpc_request *req, int offset,
- struct mds_update_record *r)
-{
- struct mds_rec_create *rec = lustre_msg_buf(req->rq_reqmsg, offset);
- ENTRY;
-
- if (req->rq_reqmsg->bufcount < offset + 2 ||
- req->rq_reqmsg->buflens[offset] != sizeof(*rec))
- RETURN(-EFAULT);
-
- r->ur_fsuid = NTOH__u32(rec->cr_fsuid);
- r->ur_fsgid = NTOH__u32(rec->cr_fsgid);
- r->ur_cap = NTOH__u32(rec->cr_cap);
- r->ur_fid1 = &rec->cr_fid;
- r->ur_fid2 = &rec->cr_replayfid;
- r->ur_mode = NTOH__u32(rec->cr_mode);
- r->ur_rdev = NTOH__u64(rec->cr_rdev);
- r->ur_uid = NTOH__u32(rec->cr_uid);
- r->ur_gid = NTOH__u32(rec->cr_gid);
- r->ur_time = NTOH__u64(rec->cr_time);
-
- r->ur_name = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
-
- if (req->rq_reqmsg->bufcount == offset + 3) {
- r->ur_tgt = lustre_msg_buf(req->rq_reqmsg, offset + 2);
- r->ur_tgtlen = req->rq_reqmsg->buflens[offset + 2];
- } else {
- r->ur_tgt = NULL;
- r->ur_tgtlen = 0;
- }
- RETURN(0);
-}
-
-static int mds_link_unpack(struct ptlrpc_request *req, int offset,
- struct mds_update_record *r)
-{
- struct mds_rec_link *rec = lustre_msg_buf(req->rq_reqmsg, offset);
- ENTRY;
-
- if (req->rq_reqmsg->bufcount != offset + 2 ||
- req->rq_reqmsg->buflens[offset] != sizeof(*rec))
- RETURN(-EFAULT);
-
- r->ur_fsuid = NTOH__u32(rec->lk_fsuid);
- r->ur_fsgid = NTOH__u32(rec->lk_fsgid);
- r->ur_cap = NTOH__u32(rec->lk_cap);
- r->ur_fid1 = &rec->lk_fid1;
- r->ur_fid2 = &rec->lk_fid2;
-
- r->ur_name = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
- RETURN(0);
-}
-
-static int mds_unlink_unpack(struct ptlrpc_request *req, int offset,
- struct mds_update_record *r)
-{
- struct mds_rec_unlink *rec = lustre_msg_buf(req->rq_reqmsg, offset);
- ENTRY;
-
- if (req->rq_reqmsg->bufcount != offset + 2 ||
- req->rq_reqmsg->buflens[offset] != sizeof(*rec))
- RETURN(-EFAULT);
-
- r->ur_fsuid = NTOH__u32(rec->ul_fsuid);
- r->ur_fsgid = NTOH__u32(rec->ul_fsgid);
- r->ur_cap = NTOH__u32(rec->ul_cap);
- r->ur_mode = NTOH__u32(rec->ul_mode);
- r->ur_fid1 = &rec->ul_fid1;
- r->ur_fid2 = &rec->ul_fid2;
-
- r->ur_name = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
- RETURN(0);
-}
-
-static int mds_rename_unpack(struct ptlrpc_request *req, int offset,
- struct mds_update_record *r)
-{
- struct mds_rec_rename *rec = lustre_msg_buf(req->rq_reqmsg, offset);
- ENTRY;
-
- if (req->rq_reqmsg->bufcount != offset + 3 ||
- req->rq_reqmsg->buflens[offset] != sizeof(*rec))
- RETURN(-EFAULT);
-
- r->ur_fsuid = NTOH__u32(rec->rn_fsuid);
- r->ur_fsgid = NTOH__u32(rec->rn_fsgid);
- r->ur_cap = NTOH__u32(rec->rn_cap);
- r->ur_fid1 = &rec->rn_fid1;
- r->ur_fid2 = &rec->rn_fid2;
-
- r->ur_name = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- r->ur_namelen = req->rq_reqmsg->buflens[offset + 1];
-
- r->ur_tgt = lustre_msg_buf(req->rq_reqmsg, offset + 2);
- r->ur_tgtlen = req->rq_reqmsg->buflens[offset + 2];
- RETURN(0);
-}
-
-typedef int (*update_unpacker)(struct ptlrpc_request *req, int offset,
- struct mds_update_record *r);
-
-static update_unpacker mds_unpackers[REINT_MAX + 1] = {
- [REINT_SETATTR] mds_setattr_unpack,
- [REINT_CREATE] mds_create_unpack,
- [REINT_LINK] mds_link_unpack,
- [REINT_UNLINK] mds_unlink_unpack,
- [REINT_RENAME] mds_rename_unpack,
-};
-
-int mds_update_unpack(struct ptlrpc_request *req, int offset,
- struct mds_update_record *rec)
-{
- __u32 *opcode = lustre_msg_buf(req->rq_reqmsg, offset);
- int rc, realop;
- ENTRY;
-
- if (!opcode || req->rq_reqmsg->buflens[offset] < sizeof(*opcode))
- RETURN(-EFAULT);
-
- realop = rec->ur_opcode = NTOH__u32(*opcode);
- realop &= REINT_OPCODE_MASK;
-
- if (realop < 0 || realop > REINT_MAX)
- RETURN(-EFAULT);
-
- rc = mds_unpackers[realop](req, offset, rec);
- RETURN(rc);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * (Un)packing of OST requests
- *
- */
-
-#define DEBUG_SUBSYSTEM S_OST
-
-#include <linux/obd_ost.h>
-#include <linux/lustre_net.h>
-
-void ost_pack_ioo(void **tmp, struct lov_stripe_md *lsm, int bufcnt)
-{
- struct obd_ioobj *ioo = *tmp;
- char *c = *tmp;
-
- ioo->ioo_id = HTON__u64(lsm->lsm_object_id);
- ioo->ioo_gr = HTON__u64(0);
- ioo->ioo_type = HTON__u32(S_IFREG);
- ioo->ioo_bufcnt = HTON__u32(bufcnt);
- *tmp = c + sizeof(*ioo);
-}
-
-void ost_unpack_ioo(void **tmp, struct obd_ioobj **ioop)
-{
- char *c = *tmp;
- struct obd_ioobj *ioo = *tmp;
- *ioop = *tmp;
-
- ioo->ioo_id = NTOH__u64(ioo->ioo_id);
- ioo->ioo_gr = NTOH__u64(ioo->ioo_gr);
- ioo->ioo_type = NTOH__u32(ioo->ioo_type);
- ioo->ioo_bufcnt = NTOH__u32(ioo->ioo_bufcnt);
- *tmp = c + sizeof(*ioo);
-}
-
-void ost_pack_niobuf(void **tmp, __u64 offset, __u32 len, __u32 flags,
- __u32 xid)
-{
- struct niobuf_remote *nb = *tmp;
- char *c = *tmp;
-
- nb->offset = HTON__u64(offset);
- nb->len = HTON__u32(len);
- nb->flags = HTON__u32(flags);
- nb->xid = HTON__u32(xid);
- *tmp = c + sizeof(*nb);
-}
-
-void ost_unpack_niobuf(void **tmp, struct niobuf_remote **nbp)
-{
- char *c = *tmp;
- struct niobuf_remote *nb = *tmp;
-
- *nbp = *tmp;
-
- nb->offset = NTOH__u64(nb->offset);
- nb->len = NTOH__u32(nb->len);
- nb->flags = NTOH__u32(nb->flags);
-
- *tmp = c + sizeof(*nb);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * lib/simple.c
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * by Peter Braam <braam@clusterfs.com>
- * and Andreas Dilger <adilger@clusterfs.com>
- */
-
-#define EXPORT_SYMTAB
-
-#include <linux/version.h>
-#include <linux/fs.h>
-#include <asm/unistd.h>
-
-#define DEBUG_SUBSYSTEM S_FILTER
-
-#include <linux/obd_support.h>
-#include <linux/obd.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_net.h>
-
-#ifdef OBD_CTXT_DEBUG
-/* Debugging check only needed during development */
-#define ASSERT_CTXT_MAGIC(magic) do { if ((magic) != OBD_RUN_CTXT_MAGIC) { \
- CERROR("bad ctxt magic\n"); LBUG(); } } while(0)
-#define ASSERT_NOT_KERNEL_CTXT(msg) do { if (segment_eq(get_fs(), get_ds())) { \
- CERROR(msg); LBUG(); } } while(0)
-#define ASSERT_KERNEL_CTXT(msg) do { if (!segment_eq(get_fs(), get_ds())) { \
- CERROR(msg); LBUG(); } } while(0)
-#else
-#define ASSERT_CTXT_MAGIC(magic) do {} while(0)
-#define ASSERT_NOT_KERNEL_CTXT(msg) do {} while(0)
-#define ASSERT_KERNEL_CTXT(msg) do {} while(0)
-#endif
-
-/* push / pop to root of obd store */
-void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *uc)
-{
- //ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
- ASSERT_CTXT_MAGIC(new_ctx->magic);
- OBD_SET_CTXT_MAGIC(save);
-
- /*
- CDEBUG(D_INFO, "== push %p->%p == cur fs %p pwd %p (%*s), pwdmnt %p\n",
- save, current, current->fs, current->fs->pwd,
- current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
- current->fs->pwdmnt);
- */
-
- save->fs = get_fs();
- save->pwd = dget(current->fs->pwd);
- save->pwdmnt = mntget(current->fs->pwdmnt);
-
- LASSERT(save->pwd);
- LASSERT(save->pwdmnt);
- LASSERT(new_ctx->pwd);
- LASSERT(new_ctx->pwdmnt);
-
- if (uc) {
- save->fsuid = current->fsuid;
- save->fsgid = current->fsgid;
- save->cap = current->cap_effective;
-
- current->fsuid = uc->ouc_fsuid;
- current->fsgid = uc->ouc_fsgid;
- current->cap_effective = uc->ouc_cap;
- }
- set_fs(new_ctx->fs);
- set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd);
-
- /*
- CDEBUG(D_INFO, "== push %p==%p == cur fs %p pwd %p (%*s), pwdmnt %p\n",
- new_ctx, current, current->fs, current->fs->pwd,
- current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
- current->fs->pwdmnt);
- */
-}
-
-void pop_ctxt(struct obd_run_ctxt *saved, struct obd_run_ctxt *new_ctx,
- struct obd_ucred *uc)
-{
- //printk("pc0");
- ASSERT_CTXT_MAGIC(saved->magic);
- //printk("pc1");
- ASSERT_KERNEL_CTXT("popping non-kernel context!\n");
-
- /*
- CDEBUG(D_INFO, " == pop %p==%p == cur %p pwd %p (%*s), pwdmnt %p\n",
- new_ctx, current, current->fs, current->fs->pwd,
- current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
- current->fs->pwdmnt);
- */
-
- LASSERT(current->fs->pwd == new_ctx->pwd);
- LASSERT(current->fs->pwdmnt == new_ctx->pwdmnt);
-
- //printk("pc2");
- set_fs(saved->fs);
- //printk("pc3\n");
- set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
- //printk("pc4");
-
- dput(saved->pwd);
- //printk("pc5");
- mntput(saved->pwdmnt);
- //printk("pc6\n");
- if (uc) {
- current->fsuid = saved->fsuid;
- current->fsgid = saved->fsgid;
- current->cap_effective = saved->cap;
- }
-
- /*
- CDEBUG(D_INFO, "== pop %p->%p == cur fs %p pwd %p (%*s), pwdmnt %p\n",
- saved, current, current->fs, current->fs->pwd,
- current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
- current->fs->pwdmnt);
- */
-}
-
-/* utility to make a file */
-struct dentry *simple_mknod(struct dentry *dir, char *name, int mode)
-{
- struct dentry *dchild;
- int err = 0;
- ENTRY;
-
- ASSERT_KERNEL_CTXT("kernel doing mknod outside kernel context\n");
- CDEBUG(D_INODE, "creating file %*s\n", (int)strlen(name), name);
-
- down(&dir->d_inode->i_sem);
- dchild = lookup_one_len(name, dir, strlen(name));
- if (IS_ERR(dchild))
- GOTO(out, PTR_ERR(dchild));
-
- if (dchild->d_inode) {
- if ((dchild->d_inode->i_mode & S_IFMT) != S_IFREG)
- GOTO(out, err = -EEXIST);
-
- GOTO(out, dchild);
- }
-
- err = vfs_create(dir->d_inode, dchild, (mode & ~S_IFMT) | S_IFREG);
- EXIT;
-out:
- up(&dir->d_inode->i_sem);
- if (err) {
- dput(dchild);
- RETURN(ERR_PTR(err));
- }
-
- RETURN(dchild);
-}
-
-/* utility to make a directory */
-struct dentry *simple_mkdir(struct dentry *dir, char *name, int mode)
-{
- struct dentry *dchild;
- int err = 0;
- ENTRY;
-
- ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
- CDEBUG(D_INODE, "creating directory %*s\n", (int)strlen(name), name);
- down(&dir->d_inode->i_sem);
- dchild = lookup_one_len(name, dir, strlen(name));
- if (IS_ERR(dchild))
- GOTO(out, PTR_ERR(dchild));
-
- if (dchild->d_inode) {
- if (!S_ISDIR(dchild->d_inode->i_mode))
- GOTO(out, err = -ENOTDIR);
-
- GOTO(out, dchild);
- }
-
- err = vfs_mkdir(dir->d_inode, dchild, mode);
- EXIT;
-out:
- up(&dir->d_inode->i_sem);
- if (err) {
- dput(dchild);
- RETURN(ERR_PTR(err));
- }
-
- RETURN(dchild);
-}
-
-/*
- * Read a file from within kernel context. Prior to calling this
- * function we should already have done a push_ctxt().
- */
-int lustre_fread(struct file *file, char *str, int len, loff_t *off)
-{
- ASSERT_KERNEL_CTXT("kernel doing read outside kernel context\n");
- if (!file || !file->f_op || !file->f_op->read || !off)
- RETURN(-ENOSYS);
-
- return file->f_op->read(file, str, len, off);
-}
-
-/*
- * Write a file from within kernel context. Prior to calling this
- * function we should already have done a push_ctxt().
- */
-int lustre_fwrite(struct file *file, const char *str, int len, loff_t *off)
-{
- ASSERT_KERNEL_CTXT("kernel doing write outside kernel context\n");
- if (!file || !file->f_op || !off)
- RETURN(-ENOSYS);
-
- if (!file->f_op->write)
- RETURN(-EROFS);
-
- return file->f_op->write(file, str, len, off);
-}
-
-/*
- * Sync a file from within kernel context. Prior to calling this
- * function we should already have done a push_ctxt().
- */
-int lustre_fsync(struct file *file)
-{
- ASSERT_KERNEL_CTXT("kernel doing sync outside kernel context\n");
- if (!file || !file->f_op || !file->f_op->fsync)
- RETURN(-ENOSYS);
-
- return file->f_op->fsync(file, file->f_dentry, 0);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- * Author: Peter J. Braam <braam@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- * Author: Mike Shaver <shaver@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Target-common OBD method implementations and utility functions.
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_OST /* XXX WRONG */
-
-#include <linux/module.h>
-#include <linux/obd_ost.h>
-#include <linux/lustre_net.h>
-#include <linux/lustre_dlm.h>
-
-int target_handle_connect(struct ptlrpc_request *req)
-{
- struct obd_device *target;
- struct obd_export *export;
- struct obd_import *dlmimp;
- struct lustre_handle conn;
- char *tgtuuid, *cluuid;
- int rc, i;
- ENTRY;
-
- tgtuuid = lustre_msg_buf(req->rq_reqmsg, 0);
- if (req->rq_reqmsg->buflens[0] > 37) {
- CERROR("bad target UUID for connect\n");
- GOTO(out, rc = -EINVAL);
- }
-
- cluuid = lustre_msg_buf(req->rq_reqmsg, 1);
- if (req->rq_reqmsg->buflens[1] > 37) {
- CERROR("bad client UUID for connect\n");
- GOTO(out, rc = -EINVAL);
- }
-
- i = class_uuid2dev(tgtuuid);
- if (i == -1) {
- CERROR("UUID '%s' not found for connect\n", tgtuuid);
- GOTO(out, rc = -ENODEV);
- }
-
- target = &obd_dev[i];
- if (!target)
- GOTO(out, rc = -ENODEV);
-
- conn.addr = req->rq_reqmsg->addr;
- conn.cookie = req->rq_reqmsg->cookie;
-
- rc = obd_connect(&conn, target, cluuid, ptlrpc_recovd,
- target_revoke_connection);
- /* EALREADY indicates a reconnection, send the reply normally. */
- if (rc && rc != EALREADY)
- GOTO(out, rc);
-
- rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- GOTO(out, rc);
- req->rq_repmsg->addr = conn.addr;
- req->rq_repmsg->cookie = conn.cookie;
-
- export = class_conn2export(&conn);
- LASSERT(export);
-
- req->rq_export = export;
- export->exp_connection = ptlrpc_get_connection(&req->rq_peer, cluuid);
- if (req->rq_connection != NULL)
- ptlrpc_put_connection(req->rq_connection);
- req->rq_connection = ptlrpc_connection_addref(export->exp_connection);
-
- spin_lock(&export->exp_connection->c_lock);
- list_add(&export->exp_conn_chain, &export->exp_connection->c_exports);
- spin_unlock(&export->exp_connection->c_lock);
- recovd_conn_manage(export->exp_connection, ptlrpc_recovd,
- target_revoke_connection);
-
- dlmimp = &export->exp_ldlm_data.led_import;
- dlmimp->imp_connection = req->rq_connection;
- dlmimp->imp_client = &export->exp_obd->obd_ldlm_client;
- dlmimp->imp_handle.addr = req->rq_reqmsg->addr;
- dlmimp->imp_handle.cookie = req->rq_reqmsg->cookie;
- dlmimp->imp_obd = /* LDLM! */ NULL;
- spin_lock_init(&dlmimp->imp_lock);
- dlmimp->imp_level = LUSTRE_CONN_FULL;
-out:
- req->rq_status = rc;
- RETURN(rc);
-}
-
-int target_handle_disconnect(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- int rc;
- ENTRY;
-
- rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
-
- req->rq_status = obd_disconnect(conn);
-
- RETURN(0);
-}
-
-static int target_disconnect_client(struct ptlrpc_connection *conn)
-{
- struct list_head *expiter, *n;
- struct lustre_handle hdl;
- struct obd_export *exp;
- int rc;
- ENTRY;
-
- list_for_each_safe(expiter, n, &conn->c_exports) {
- exp = list_entry(expiter, struct obd_export, exp_conn_chain);
-
- hdl.addr = (__u64)(unsigned long)exp;
- hdl.cookie = exp->exp_cookie;
- rc = obd_disconnect(&hdl);
- if (rc)
- CERROR("disconnecting export %p failed: %d\n", exp, rc);
- }
-
- /* XXX spank the connection (it's frozen in _RECOVD for now!) */
- RETURN(0);
-}
-
-static int target_fence_failed_connection(struct ptlrpc_connection *conn)
-{
- ENTRY;
-
- conn->c_recovd_data.rd_phase = RD_PREPARED;
-
- RETURN(0);
-}
-
-int target_revoke_connection(struct recovd_data *rd, int phase)
-{
- struct ptlrpc_connection *conn = class_rd2conn(rd);
-
- LASSERT(conn);
- ENTRY;
-
- switch (phase) {
- case PTLRPC_RECOVD_PHASE_PREPARE:
- RETURN(target_fence_failed_connection(conn));
- case PTLRPC_RECOVD_PHASE_RECOVER:
- RETURN(target_disconnect_client(conn));
- case PTLRPC_RECOVD_PHASE_FAILURE:
- LBUG();
- RETURN(0);
- }
-
- LBUG();
- RETURN(-ENOSYS);
-}
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=
-
-MODULE = llite
-modulefs_DATA = llite.o
-EXTRA_PROGRAMS = llite
-
-LINX= ll_pack.c
-
-llite_SOURCES = dcache.c commit_callback.c super.c rw.c super25.c
-llite_SOURCES += file.c dir.c sysctl.c symlink.c $(LINX)
-llite_SOURCES += recover.c namei.c lproc_llite.c
-
-ll_pack.c:
- test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c .
-
-include $(top_srcdir)/Rules
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * The daemon that causes completed but not committed transactions
- * on the MDS to be flushed periodically when they are committed.
- * A gratuitous getattr RPC is made to the MDS to discover the
- * last committed record.
- *
- * Lustre High Availability Daemon
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * by Peter Braam <braam@clusterfs.com>
- *
- */
-
-#define EXPORT_SYMTAB
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/kmod.h>
-#include <linux/quotaops.h>
-#include <asm/unistd.h>
-#include <asm/uaccess.h>
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_lite.h>
-#include <linux/lustre_lib.h>
-
-static int ll_commitcbd_check_event(struct ll_sb_info *sbi)
-{
- int rc = 0;
- ENTRY;
-
- spin_lock(&sbi->ll_commitcbd_lock);
- if (sbi->ll_commitcbd_flags & LL_COMMITCBD_STOPPING) {
- GOTO(out, rc = 1);
- }
-
- out:
- spin_unlock(&sbi->ll_commitcbd_lock);
- RETURN(rc);
-}
-
-static int ll_commitcbd_main(void *arg)
-{
- struct ll_sb_info *sbi = (struct ll_sb_info *)arg;
-
- ENTRY;
-
- lock_kernel();
- daemonize();
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- our_recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
-#else
- sigfillset(¤t->blocked);
- our_recalc_sigpending(current);
-#endif
-
- sprintf(current->comm, "lustre_commitcbd");
- unlock_kernel();
-
- /* Record that the thread is running */
- sbi->ll_commitcbd_waketime = CURRENT_TIME;
- sbi->ll_commitcbd_timeout = 10 * HZ;
- sbi->ll_commitcbd_thread = current;
- sbi->ll_commitcbd_flags = LL_COMMITCBD_RUNNING;
- wake_up(&sbi->ll_commitcbd_ctl_waitq);
-
- /* And now, loop forever on requests */
- while (1) {
- wait_event(sbi->ll_commitcbd_waitq,
- ll_commitcbd_check_event(sbi));
-
- spin_lock(&sbi->ll_commitcbd_lock);
- if (sbi->ll_commitcbd_flags & LL_COMMITCBD_STOPPING) {
- spin_unlock(&sbi->ll_commitcbd_lock);
- CERROR("lustre_commitd quitting\n");
- EXIT;
- break;
- }
-
- schedule_timeout(sbi->ll_commitcbd_timeout);
- CERROR("commit callback daemon woken up - FIXME\n");
- spin_unlock(&sbi->ll_commitcbd_lock);
- }
-
- sbi->ll_commitcbd_thread = NULL;
- sbi->ll_commitcbd_flags = LL_COMMITCBD_STOPPED;
- wake_up(&sbi->ll_commitcbd_ctl_waitq);
- CDEBUG(D_NET, "commit callback daemon exiting %d\n", current->pid);
- RETURN(0);
-}
-
-
-
-int ll_commitcbd_setup(struct ll_sb_info *sbi)
-{
- int rc;
- ENTRY;
-
- rc = kernel_thread(ll_commitcbd_main, (void *) sbi,
- CLONE_VM | CLONE_FS | CLONE_FILES);
- if (rc < 0) {
- CERROR("cannot start thread\n");
- RETURN(rc);
- }
- wait_event(sbi->ll_commitcbd_ctl_waitq,
- sbi->ll_commitcbd_flags & LL_COMMITCBD_RUNNING);
- RETURN(0);
-}
-
-
-int ll_commitcbd_cleanup(struct ll_sb_info *sbi)
-{
- sbi->ll_commitcbd_flags = LL_COMMITCBD_STOPPING;
-
- wake_up(&sbi->ll_commitcbd_waitq);
- wait_event(sbi->ll_commitcbd_ctl_waitq,
- sbi->ll_commitcbd_flags & LL_COMMITCBD_STOPPED);
- RETURN(0);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2001, 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/quotaops.h>
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/obd_support.h>
-#include <linux/lustre_lite.h>
-#include <linux/lustre_idl.h>
-#include <linux/lustre_dlm.h>
-
-extern struct address_space_operations ll_aops;
-
-void ll_release(struct dentry *de)
-{
- ENTRY;
-
- OBD_FREE(de->d_fsdata, sizeof(struct ll_dentry_data));
- EXIT;
-}
-
-extern void d_delete_aliases(struct inode *);
-void ll_intent_release(struct dentry *de, struct lookup_intent *it)
-{
- struct lustre_handle *handle;
- ENTRY;
-
- /* XXX the check for RENAME2 is a workaround for old kernels
- which call intent_release twice in rename
- */
- if (it == NULL || it->it_op == IT_RENAME2) {
- EXIT;
- return;
- }
-
- LASSERT(ll_d2d(de) != NULL);
-
- if (it->it_lock_mode) {
- handle = (struct lustre_handle *)it->it_lock_handle;
- if (it->it_op == IT_SETATTR) {
- int rc;
- ldlm_lock_decref(handle, it->it_lock_mode);
- rc = ldlm_cli_cancel(handle);
- if (rc < 0)
- CERROR("ldlm_cli_cancel: %d\n", rc);
- } else
- ldlm_lock_decref(handle, it->it_lock_mode);
-
- /* intent_release may be called multiple times, and we don't
- * want to double-decref this lock (see bug 494) */
- it->it_lock_mode = 0;
- }
-
- if (!de->d_it || it->it_op == IT_RELEASED_MAGIC) {
- EXIT;
- return;
- }
-
- if (de->d_it == it)
- LL_GET_INTENT(de, it);
-
- EXIT;
-}
-
-extern struct dentry *ll_find_alias(struct inode *, struct dentry *);
-
-static int revalidate2_finish(int flag, struct ptlrpc_request *request,
- struct dentry **de,
- struct lookup_intent *it,
- int offset, obd_id ino)
-{
- ldlm_lock_set_data((struct lustre_handle *)it->it_lock_handle,
- (*de)->d_inode, sizeof(*((*de)->d_inode)));
- ptlrpc_req_finished(request);
- return 0;
-}
-
-static int ll_have_lock(struct dentry *de)
-{
- struct ll_sb_info *sbi = ll_s2sbi(de->d_sb);
- struct lustre_handle lockh;
- __u64 res_id[RES_NAME_SIZE] = {0};
- struct obd_device *obddev;
- ENTRY;
-
- if (!de->d_inode)
- RETURN(0);
-
- obddev = class_conn2obd(&sbi->ll_mdc_conn);
- res_id[0] = de->d_inode->i_ino;
- res_id[1] = de->d_inode->i_generation;
-
- CDEBUG(D_INFO, "trying to match res "LPU64"\n", res_id[0]);
-
- if (ldlm_lock_match(obddev->obd_namespace, res_id, LDLM_PLAIN,
- NULL, 0, LCK_PR, &lockh)) {
- ldlm_lock_decref(&lockh, LCK_PR);
- RETURN(1);
- }
-
- if (ldlm_lock_match(obddev->obd_namespace, res_id, LDLM_PLAIN,
- NULL, 0, LCK_PW, &lockh)) {
- ldlm_lock_decref(&lockh, LCK_PW);
- RETURN(1);
- }
- RETURN(0);
-}
-
-int ll_revalidate2(struct dentry *de, int flags, struct lookup_intent *it)
-{
- int rc;
- ENTRY;
-
- /* We don't want to cache negative dentries, so return 0 immediately.
- * We believe that this is safe, that negative dentries cannot be
- * pinned by someone else */
- if (de->d_inode == NULL) {
- CDEBUG(D_INODE, "negative dentry: ret 0 to force lookup2\n");
- RETURN(0);
- }
-
-// if (it == NULL && ll_have_lock(de))
-// RETURN(1);
-
- rc = ll_intent_lock(de->d_parent->d_inode, &de, it, revalidate2_finish);
- if (rc < 0) {
- /* Something bad happened; overwrite it_status? */
- CERROR("ll_intent_lock: %d\n", rc);
- }
- /* unfortunately ll_intent_lock may cause a callback and revoke our
- dentry */
- spin_lock(&dcache_lock);
- list_del_init(&de->d_hash);
- spin_unlock(&dcache_lock);
- d_rehash(de);
-
- RETURN(1);
-}
-
-int ll_set_dd(struct dentry *de)
-{
- ENTRY;
- LASSERT(de != NULL);
-
- lock_kernel();
-
- if (de->d_fsdata != NULL) {
- CERROR("dentry %p already has d_fsdata set\n", de);
- } else {
- OBD_ALLOC(de->d_fsdata, sizeof(struct ll_dentry_data));
- sema_init(&ll_d2d(de)->lld_it_sem, 1);
- }
-
- unlock_kernel();
-
- RETURN(0);
-}
-
-struct dentry_operations ll_d_ops = {
- .d_revalidate2 = ll_revalidate2,
- .d_intent_release = ll_intent_release,
- .d_release = ll_release,
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 1992, 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * from
- *
- * linux/fs/minix/dir.c
- * linux/fs/ext2/dir.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * ext2 directory handling functions
- *
- * Big-endian to little-endian byte-swapping/bitmaps by
- * David S. Miller (davem@caip.rutgers.edu), 1995
- *
- * All code that works with directory layout had been switched to pagecache
- * and moved here. AV
- *
- * Adapted for Lustre Light
- * Copyright (C) 2002, Cluster File Systems, Inc.
- *
- */
-
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/pagemap.h>
-#include <linux/mm.h>
-#include <linux/version.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#include <linux/locks.h> // for wait_on_buffer
-#else
-#include <linux/buffer_head.h> // for wait_on_buffer
-#endif
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_idl.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_lite.h>
-#include <linux/lustre_dlm.h>
-
-typedef struct ext2_dir_entry_2 ext2_dirent;
-
-#define PageChecked(page) test_bit(PG_checked, &(page)->flags)
-#define SetPageChecked(page) set_bit(PG_checked, &(page)->flags)
-
-
-static int ll_dir_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
-{
- return 0;
-}
-
-/* returns the page unlocked, but with a reference */
-static int ll_dir_readpage(struct file *file, struct page *page)
-{
- struct inode *inode = page->mapping->host;
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- char *buf;
- __u64 offset;
- int rc = 0;
- struct ptlrpc_request *request;
- struct lustre_handle lockh;
- struct mds_body *body;
- struct lookup_intent it = { .it_op = IT_READDIR };
-
- ENTRY;
-
- if ((inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_SHIFT <= page->index){
- memset(kmap(page), 0, PAGE_CACHE_SIZE);
- kunmap(page);
- GOTO(readpage_out, rc);
- }
-
- rc = mdc_enqueue(&sbi->ll_mdc_conn, LDLM_PLAIN, &it, LCK_PR, inode,
- NULL, &lockh, NULL, 0, inode, sizeof(*inode));
- request = (struct ptlrpc_request *)it.it_data;
- if (request)
- ptlrpc_req_finished(request);
- if (rc != ELDLM_OK) {
- CERROR("lock enqueue: err: %d\n", rc);
- unlock_page(page);
- RETURN(rc);
- }
- ldlm_lock_dump((void *)(unsigned long)lockh.addr);
-
- if (PageUptodate(page)) {
- CERROR("Explain this please?\n");
- GOTO(readpage_out, rc);
- }
-
- offset = page->index << PAGE_SHIFT;
- buf = kmap(page);
- rc = mdc_readpage(&sbi->ll_mdc_conn, inode->i_ino,
- S_IFDIR, offset, buf, &request);
- kunmap(page);
- if (!rc) {
- body = lustre_msg_buf(request->rq_repmsg, 0);
- if (!body)
- rc = -EINVAL;
- else
- inode->i_size = body->size;
- }
- ptlrpc_req_finished(request);
- EXIT;
-
- readpage_out:
- if (!rc)
- SetPageUptodate(page);
-
- unlock_page(page);
- rc = ll_unlock(LCK_PR, &lockh);
- if (rc != ELDLM_OK)
- CERROR("ll_unlock: err: %d\n", rc);
- return rc;
-} /* ll_dir_readpage */
-
-struct address_space_operations ll_dir_aops = {
- readpage: ll_dir_readpage,
- prepare_write: ll_dir_prepare_write
-};
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3))
-int waitfor_one_page(struct page *page)
-{
- int error = 0;
- struct buffer_head *bh, *head = page->buffers;
-
- bh = head;
- do {
- wait_on_buffer(bh);
- if (buffer_req(bh) && !buffer_uptodate(bh))
- error = -EIO;
- } while ((bh = bh->b_this_page) != head);
- return error;
-}
-#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
-int waitfor_one_page(struct page *page)
-{
- wait_on_page_locked(page);
- return 0;
-}
-#endif
-
-/*
- * ext2 uses block-sized chunks. Arguably, sector-sized ones would be
- * more robust, but we have what we have
- */
-static inline unsigned ext2_chunk_size(struct inode *inode)
-{
- return inode->i_sb->s_blocksize;
-}
-
-static inline void ext2_put_page(struct page *page)
-{
- kunmap(page);
- page_cache_release(page);
-}
-
-static inline unsigned long dir_pages(struct inode *inode)
-{
- return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
-}
-
-extern void set_page_clean(struct page *page);
-
-static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to)
-{
- struct inode *dir = page->mapping->host;
- loff_t new_size = (page->index << PAGE_CACHE_SHIFT) + to;
- int err = 0;
-
- dir->i_version = ++event;
- if (new_size > dir->i_size)
- dir->i_size = new_size;
- SetPageUptodate(page);
- set_page_clean(page);
-
- //page->mapping->a_ops->commit_write(NULL, page, from, to);
- //if (IS_SYNC(dir))
- // err = waitfor_one_page(page);
- return err;
-}
-
-static void ext2_check_page(struct page *page)
-{
- struct inode *dir = page->mapping->host;
- unsigned chunk_size = ext2_chunk_size(dir);
- char *kaddr = page_address(page);
- // u32 max_inumber = le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count);
- unsigned offs, rec_len;
- unsigned limit = PAGE_CACHE_SIZE;
- ext2_dirent *p;
- char *error;
-
- if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) {
- limit = dir->i_size & ~PAGE_CACHE_MASK;
- if (limit & (chunk_size - 1)) {
- CERROR("limit %d dir size %lld index %ld\n",
- limit, dir->i_size, page->index);
- goto Ebadsize;
- }
- for (offs = limit; offs<PAGE_CACHE_SIZE; offs += chunk_size) {
- ext2_dirent *p = (ext2_dirent*)(kaddr + offs);
- p->rec_len = cpu_to_le16(chunk_size);
- p->name_len = 0;
- p->inode = 0;
- }
- if (!limit)
- goto out;
- }
- for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) {
- p = (ext2_dirent *)(kaddr + offs);
- rec_len = le16_to_cpu(p->rec_len);
-
- if (rec_len < EXT2_DIR_REC_LEN(1))
- goto Eshort;
- if (rec_len & 3)
- goto Ealign;
- if (rec_len < EXT2_DIR_REC_LEN(p->name_len))
- goto Enamelen;
- if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1))
- goto Espan;
- // if (le32_to_cpu(p->inode) > max_inumber)
- //goto Einumber;
- }
- if (offs != limit)
- goto Eend;
-out:
- SetPageChecked(page);
- return;
-
- /* Too bad, we had an error */
-
-Ebadsize:
- CERROR("ext2_check_page"
- "size of directory #%lu is not a multiple of chunk size\n",
- dir->i_ino
- );
- goto fail;
-Eshort:
- error = "rec_len is smaller than minimal";
- goto bad_entry;
-Ealign:
- error = "unaligned directory entry";
- goto bad_entry;
-Enamelen:
- error = "rec_len is too small for name_len";
- goto bad_entry;
-Espan:
- error = "directory entry across blocks";
- goto bad_entry;
- //Einumber:
- // error = "inode out of bounds";
-bad_entry:
- CERROR("ext2_check_page: bad entry in directory #%lu: %s - "
- "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
- dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
- (unsigned long) le32_to_cpu(p->inode),
- rec_len, p->name_len);
- goto fail;
-Eend:
- p = (ext2_dirent *)(kaddr + offs);
- CERROR("ext2_check_page"
- "entry in directory #%lu spans the page boundary"
- "offset=%lu, inode=%lu",
- dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
- (unsigned long) le32_to_cpu(p->inode));
-fail:
- SetPageChecked(page);
- SetPageError(page);
- LBUG();
-}
-
-static struct page * ll_get_page(struct inode *dir, unsigned long n)
-{
- struct address_space *mapping = dir->i_mapping;
- struct page *page = read_cache_page(mapping, n,
- (filler_t*)mapping->a_ops->readpage, NULL);
- if (!IS_ERR(page)) {
- wait_on_page(page);
- kmap(page);
- if (!PageUptodate(page))
- goto fail;
- if (!PageChecked(page))
- ext2_check_page(page);
- if (PageError(page))
- goto fail;
- }
- return page;
-
-fail:
- ext2_put_page(page);
- return ERR_PTR(-EIO);
-}
-
-/*
- * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
- *
- * len <= EXT2_NAME_LEN and de != NULL are guaranteed by caller.
- */
-static inline int ext2_match (int len, const char * const name,
- struct ext2_dir_entry_2 * de)
-{
- if (len != de->name_len)
- return 0;
- if (!de->inode)
- return 0;
- return !memcmp(name, de->name, len);
-}
-
-/*
- * p is at least 6 bytes before the end of page
- */
-static inline ext2_dirent *ext2_next_entry(ext2_dirent *p)
-{
- return (ext2_dirent *)((char*)p + le16_to_cpu(p->rec_len));
-}
-
-static inline unsigned
-ext2_validate_entry(char *base, unsigned offset, unsigned mask)
-{
- ext2_dirent *de = (ext2_dirent*)(base + offset);
- ext2_dirent *p = (ext2_dirent*)(base + (offset&mask));
- while ((char*)p < (char*)de)
- p = ext2_next_entry(p);
- return (char *)p - base;
-}
-
-static unsigned char ext2_filetype_table[EXT2_FT_MAX] = {
- [EXT2_FT_UNKNOWN] DT_UNKNOWN,
- [EXT2_FT_REG_FILE] DT_REG,
- [EXT2_FT_DIR] DT_DIR,
- [EXT2_FT_CHRDEV] DT_CHR,
- [EXT2_FT_BLKDEV] DT_BLK,
- [EXT2_FT_FIFO] DT_FIFO,
- [EXT2_FT_SOCK] DT_SOCK,
- [EXT2_FT_SYMLINK] DT_LNK,
-};
-
-static unsigned int ll_dt2fmt[DT_WHT + 1] = {
- [EXT2_FT_UNKNOWN] 0,
- [EXT2_FT_REG_FILE] S_IFREG,
- [EXT2_FT_DIR] S_IFDIR,
- [EXT2_FT_CHRDEV] S_IFCHR,
- [EXT2_FT_BLKDEV] S_IFBLK,
- [EXT2_FT_FIFO] S_IFIFO,
- [EXT2_FT_SOCK] S_IFSOCK,
- [EXT2_FT_SYMLINK] S_IFLNK
-};
-
-#define S_SHIFT 12
-static unsigned char ext2_type_by_mode[S_IFMT >> S_SHIFT] = {
- [S_IFREG >> S_SHIFT] EXT2_FT_REG_FILE,
- [S_IFDIR >> S_SHIFT] EXT2_FT_DIR,
- [S_IFCHR >> S_SHIFT] EXT2_FT_CHRDEV,
- [S_IFBLK >> S_SHIFT] EXT2_FT_BLKDEV,
- [S_IFIFO >> S_SHIFT] EXT2_FT_FIFO,
- [S_IFSOCK >> S_SHIFT] EXT2_FT_SOCK,
- [S_IFLNK >> S_SHIFT] EXT2_FT_SYMLINK,
-};
-
-static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode)
-{
- mode_t mode = inode->i_mode;
- de->file_type = ext2_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
-}
-
-int ll_readdir(struct file * filp, void * dirent, filldir_t filldir)
-{
- loff_t pos = filp->f_pos;
- struct inode *inode = filp->f_dentry->d_inode;
- // XXX struct super_block *sb = inode->i_sb;
- unsigned offset = pos & ~PAGE_CACHE_MASK;
- unsigned long n = pos >> PAGE_CACHE_SHIFT;
- unsigned long npages = dir_pages(inode);
- unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
- unsigned char *types = NULL;
- int need_revalidate = (filp->f_version != inode->i_version);
- ENTRY;
-
- if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
- GOTO(done, 0);
-
- types = ext2_filetype_table;
-
- for ( ; n < npages; n++, offset = 0) {
- char *kaddr, *limit;
- ext2_dirent *de;
- struct page *page;
-
- page = ll_get_page(inode, n);
-
- /* size might have been updated by mdc_readpage */
- npages = dir_pages(inode);
-
- if (IS_ERR(page))
- continue;
- kaddr = page_address(page);
- if (need_revalidate) {
- offset = ext2_validate_entry(kaddr, offset, chunk_mask);
- need_revalidate = 0;
- }
- de = (ext2_dirent *)(kaddr+offset);
- limit = kaddr + PAGE_CACHE_SIZE - EXT2_DIR_REC_LEN(1);
- for ( ;(char*)de <= limit; de = ext2_next_entry(de))
- if (de->inode) {
- int over;
- unsigned char d_type = DT_UNKNOWN;
-
- if (types && de->file_type < EXT2_FT_MAX)
- d_type = types[de->file_type];
-
- offset = (char *)de - kaddr;
- over = filldir(dirent, de->name, de->name_len,
- (n<<PAGE_CACHE_SHIFT) | offset,
- le32_to_cpu(de->inode), d_type);
- if (over) {
- ext2_put_page(page);
- GOTO(done,0);
- }
- }
- ext2_put_page(page);
- }
-
-done:
- filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
- filp->f_version = inode->i_version;
- UPDATE_ATIME(inode);
- RETURN(0);
-}
-
-/*
- * ext2_find_entry()
- *
- * finds an entry in the specified directory with the wanted name. It
- * returns the page in which the entry was found, and the entry itself
- * (as a parameter - res_dir). Page is returned mapped and unlocked.
- * Entry is guaranteed to be valid.
- */
-struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
- struct dentry *dentry, struct page ** res_page)
-{
- const char *name = dentry->d_name.name;
- int namelen = dentry->d_name.len;
- unsigned reclen = EXT2_DIR_REC_LEN(namelen);
- unsigned long start, n;
- unsigned long npages = dir_pages(dir);
- struct page *page = NULL;
- ext2_dirent * de;
-
- /* OFFSET_CACHE */
- *res_page = NULL;
-
- // start = dir->u.ext2_i.i_dir_start_lookup;
- start = 0;
- if (start >= npages)
- start = 0;
- n = start;
- do {
- char *kaddr;
- page = ll_get_page(dir, n);
- if (!IS_ERR(page)) {
- kaddr = page_address(page);
- de = (ext2_dirent *) kaddr;
- kaddr += PAGE_CACHE_SIZE - reclen;
- while ((char *) de <= kaddr) {
- if (ext2_match (namelen, name, de))
- goto found;
- de = ext2_next_entry(de);
- }
- ext2_put_page(page);
- }
- if (++n >= npages)
- n = 0;
- } while (n != start);
- return NULL;
-
-found:
- *res_page = page;
- // dir->u.ext2_i.i_dir_start_lookup = n;
- return de;
-}
-
-struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
-{
- struct page *page = ll_get_page(dir, 0);
- ext2_dirent *de = NULL;
-
- if (!IS_ERR(page)) {
- de = ext2_next_entry((ext2_dirent *) page_address(page));
- *p = page;
- }
- return de;
-}
-
-obd_id ll_inode_by_name(struct inode * dir, struct dentry *dentry, int *type)
-{
- obd_id res = 0;
- struct ext2_dir_entry_2 * de;
- struct page *page;
-
- de = ext2_find_entry (dir, dentry, &page);
- if (de) {
- res = le32_to_cpu(de->inode);
- *type = ll_dt2fmt[de->file_type];
- kunmap(page);
- page_cache_release(page);
- }
- return res;
-}
-
-/* Releases the page */
-void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
- struct page *page, struct inode *inode)
-{
- unsigned from = (char *) de - (char *) page_address(page);
- unsigned to = from + le16_to_cpu(de->rec_len);
- int err;
-
- lock_page(page);
- err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
- if (err)
- LBUG();
- de->inode = cpu_to_le32(inode->i_ino);
- ext2_set_de_type (de, inode);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
- err = ext2_commit_chunk(page, from, to);
- unlock_page(page);
- ext2_put_page(page);
-}
-
-/*
- * Parent is locked.
- */
-int ll_add_link (struct dentry *dentry, struct inode *inode)
-{
- struct inode *dir = dentry->d_parent->d_inode;
- const char *name = dentry->d_name.name;
- int namelen = dentry->d_name.len;
- unsigned reclen = EXT2_DIR_REC_LEN(namelen);
- unsigned short rec_len, name_len;
- struct page *page = NULL;
- ext2_dirent * de;
- unsigned long npages = dir_pages(dir);
- unsigned long n;
- char *kaddr;
- unsigned from, to;
- int err;
-
- /* We take care of directory expansion in the same loop */
- for (n = 0; n <= npages; n++) {
- page = ll_get_page(dir, n);
- err = PTR_ERR(page);
- if (IS_ERR(page))
- goto out;
- kaddr = page_address(page);
- de = (ext2_dirent *)kaddr;
- kaddr += PAGE_CACHE_SIZE - reclen;
- while ((char *)de <= kaddr) {
- err = -EEXIST;
- if (ext2_match (namelen, name, de))
- goto out_page;
- name_len = EXT2_DIR_REC_LEN(de->name_len);
- rec_len = le16_to_cpu(de->rec_len);
- if ( n==npages && rec_len == 0) {
- CERROR("Fatal dir behaviour\n");
- goto out_page;
- }
- if (!de->inode && rec_len >= reclen)
- goto got_it;
- if (rec_len >= name_len + reclen)
- goto got_it;
- de = (ext2_dirent *) ((char *) de + rec_len);
- }
- ext2_put_page(page);
- }
- LBUG();
- return -EINVAL;
-
-got_it:
- from = (char*)de - (char*)page_address(page);
- to = from + rec_len;
- lock_page(page);
- err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
- if (err)
- goto out_unlock;
- if (de->inode) {
- ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len);
- de1->rec_len = cpu_to_le16(rec_len - name_len);
- de->rec_len = cpu_to_le16(name_len);
- de = de1;
- }
- de->name_len = namelen;
- memcpy (de->name, name, namelen);
- de->inode = cpu_to_le32(inode->i_ino);
- ext2_set_de_type (de, inode);
- CDEBUG(D_INODE, "type set to %o\n", de->file_type);
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
- err = ext2_commit_chunk(page, from, to);
-
- // change_inode happens with the commit_chunk
- /* XXX OFFSET_CACHE */
-
-out_unlock:
- unlock_page(page);
-out_page:
- ext2_put_page(page);
-out:
- return err;
-}
-
-/*
- * ext2_delete_entry deletes a directory entry by merging it with the
- * previous entry. Page is up-to-date. Releases the page.
- */
-int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page )
-{
- struct address_space *mapping = page->mapping;
- struct inode *inode = mapping->host;
- char *kaddr = page_address(page);
- unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1);
- unsigned to = ((char*)dir - kaddr) + le16_to_cpu(dir->rec_len);
- ext2_dirent * pde = NULL;
- ext2_dirent * de = (ext2_dirent *) (kaddr + from);
- int err;
-
- while ((char*)de < (char*)dir) {
- pde = de;
- de = ext2_next_entry(de);
- }
- if (pde)
- from = (char*)pde - (char*)page_address(page);
- lock_page(page);
- err = mapping->a_ops->prepare_write(NULL, page, from, to);
- if (err)
- LBUG();
- if (pde)
- pde->rec_len = cpu_to_le16(to-from);
- dir->inode = 0;
- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- err = ext2_commit_chunk(page, from, to);
- unlock_page(page);
- ext2_put_page(page);
- return err;
-}
-
-/*
- * Set the first fragment of directory.
- */
-int ext2_make_empty(struct inode *inode, struct inode *parent)
-{
- struct address_space *mapping = inode->i_mapping;
- struct page *page = grab_cache_page(mapping, 0);
- unsigned chunk_size = ext2_chunk_size(inode);
- struct ext2_dir_entry_2 * de;
- char *base;
- int err;
- ENTRY;
-
- if (!page)
- return -ENOMEM;
- base = kmap(page);
- if (!base)
- return -ENOMEM;
-
- err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size);
- if (err)
- goto fail;
-
- de = (struct ext2_dir_entry_2 *) base;
- de->name_len = 1;
- de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(1));
- memcpy (de->name, ".\0\0", 4);
- de->inode = cpu_to_le32(inode->i_ino);
- ext2_set_de_type (de, inode);
-
- de = (struct ext2_dir_entry_2 *) (base + EXT2_DIR_REC_LEN(1));
- de->name_len = 2;
- de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1));
- de->inode = cpu_to_le32(parent->i_ino);
- memcpy (de->name, "..\0", 4);
- ext2_set_de_type (de, inode);
-
- err = ext2_commit_chunk(page, 0, chunk_size);
-fail:
- kunmap(page);
- unlock_page(page);
- page_cache_release(page);
- ENTRY;
- return err;
-}
-
-/*
- * routine to check that the specified directory is empty (for rmdir)
- */
-int ext2_empty_dir (struct inode * inode)
-{
- struct page *page = NULL;
- unsigned long i, npages = dir_pages(inode);
-
- for (i = 0; i < npages; i++) {
- char *kaddr;
- ext2_dirent * de;
- page = ll_get_page(inode, i);
-
- if (IS_ERR(page))
- continue;
-
- kaddr = page_address(page);
- de = (ext2_dirent *)kaddr;
- kaddr += PAGE_CACHE_SIZE-EXT2_DIR_REC_LEN(1);
-
- while ((char *)de <= kaddr) {
- if (de->inode != 0) {
- /* check for . and .. */
- if (de->name[0] != '.')
- goto not_empty;
- if (de->name_len > 2)
- goto not_empty;
- if (de->name_len < 2) {
- if (de->inode !=
- cpu_to_le32(inode->i_ino))
- goto not_empty;
- } else if (de->name[1] != '.')
- goto not_empty;
- }
- de = ext2_next_entry(de);
- }
- ext2_put_page(page);
- }
- return 1;
-
-not_empty:
- ext2_put_page(page);
- return 0;
-}
-
-struct file_operations ll_dir_operations = {
- read: generic_read_dir,
- readdir: ll_readdir
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * linux/fs/ext2/file.c
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copyright (C) 1992, 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * from
- *
- * linux/fs/minix/file.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * ext2 fs regular file handling primitives
- *
- * 64-bit file support on 64-bit platforms by Jakub Jelinek
- * (jj@sunsite.ms.mff.cuni.cz)
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_dlm.h>
-#include <linux/lustre_lite.h>
-#include <linux/obd_lov.h> /* for lov_mds_md_size() in lov_setstripe() */
-#include <linux/random.h>
-
-int ll_inode_setattr(struct inode *inode, struct iattr *attr, int do_trunc);
-extern int ll_setattr(struct dentry *de, struct iattr *attr);
-
-int ll_create_objects(struct super_block *sb, obd_id id, uid_t uid, gid_t gid,
- struct lov_stripe_md **lsmp)
-{
- struct obdo *oa;
- int rc;
- ENTRY;
-
- oa = obdo_alloc();
- if (!oa)
- RETURN(-ENOMEM);
-
- oa->o_mode = S_IFREG | 0600;
- oa->o_id = id;
- oa->o_uid = uid;
- oa->o_gid = gid;
- oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE |
- OBD_MD_FLUID | OBD_MD_FLGID;
- rc = obd_create(ll_s2obdconn(sb), oa, lsmp);
- obdo_free(oa);
-
- if (!rc)
- LASSERT(*lsmp && (*lsmp)->lsm_object_id);
- RETURN(rc);
-}
-
-static int ll_file_open(struct inode *inode, struct file *file)
-{
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ll_inode_info *lli = ll_i2info(inode);
- struct lustre_handle *conn = ll_i2obdconn(inode);
- struct ptlrpc_request *req = NULL;
- struct ll_file_data *fd;
- struct obdo *oa;
- struct lov_stripe_md *lsm;
- struct lov_mds_md *lmm = NULL;
- int lmm_size = 0;
- int rc = 0;
- ENTRY;
-
- LASSERT(!file->private_data);
-
- lsm = lli->lli_smd;
-
- /* delayed create of object (intent created inode) */
- /* XXX object needs to be cleaned up if mdc_open fails */
- /* XXX error handling appropriate here? */
- if (lsm == NULL) {
- if (file->f_flags & O_LOV_DELAY_CREATE) {
- CDEBUG(D_INODE, "delaying object creation\n");
- RETURN(0);
- }
- down(&lli->lli_open_sem);
- /* Check to see if we lost the race */
- if (!lli->lli_smd)
- rc = ll_create_objects(inode->i_sb, inode->i_ino, 0, 0,
- &lli->lli_smd);
- up(&lli->lli_open_sem);
- if (rc)
- RETURN(rc);
-
- lsm = lli->lli_smd;
- }
-
- /* XXX We should only send this to MDS if we just created these
- * objects, except we also need to handle the user-stripe case.
- */
- rc = obd_packmd(conn, &lmm, lli->lli_smd);
- if (rc < 0)
- GOTO(out, rc);
-
- lmm_size = rc;
-
- fd = kmem_cache_alloc(ll_file_data_slab, SLAB_KERNEL);
- if (!fd) {
- if (lmm)
- obd_free_wiremd(conn, &lmm);
- GOTO(out, rc = -ENOMEM);
- }
- memset(fd, 0, sizeof(*fd));
-
- fd->fd_mdshandle.addr = (__u64)(unsigned long)file;
- get_random_bytes(&fd->fd_mdshandle.cookie,
- sizeof(fd->fd_mdshandle.cookie));
- rc = mdc_open(&sbi->ll_mdc_conn, inode->i_ino, S_IFREG | inode->i_mode,
- file->f_flags, lmm, lmm_size, &fd->fd_mdshandle, &req);
- if (lmm)
- obd_free_wiremd(conn, &lmm);
- fd->fd_req = req;
-
- /* This is the "reply" refcount. */
- ptlrpc_req_finished(req);
- if (rc)
- GOTO(out_req, -abs(rc));
- if (!fd->fd_mdshandle.addr ||
- fd->fd_mdshandle.addr == (__u64)(unsigned long)file) {
- CERROR("hmm, mdc_open didn't assign fd_mdshandle?\n");
- /* XXX handle this how, abort or is it non-fatal? */
- }
-
- oa = obdo_alloc();
- if (!oa)
- GOTO(out_mdc, rc = -EINVAL);
-
- oa->o_id = lsm->lsm_object_id;
- oa->o_mode = S_IFREG;
- oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLSIZE |
- OBD_MD_FLBLOCKS;
- rc = obd_open(ll_i2obdconn(inode), oa, lsm);
- obdo_to_inode(inode, oa, oa->o_valid & (OBD_MD_FLSIZE|OBD_MD_FLBLOCKS));
-
- obd_oa2handle(&fd->fd_osthandle, oa);
- obdo_free(oa);
-
- if (rc)
- GOTO(out_mdc, rc = -abs(rc));
-
- atomic_inc(&lli->lli_open_count);
-
- file->private_data = fd;
-
- RETURN(0);
-out_mdc:
- mdc_close(&sbi->ll_mdc_conn, inode->i_ino,
- S_IFREG, &fd->fd_mdshandle, &req);
-out_req:
- ptlrpc_req_finished(req); /* once for reply */
- ptlrpc_req_finished(req); /* once for an early "commit" */
-//out_fd:
- fd->fd_mdshandle.cookie = DEAD_HANDLE_MAGIC;
- kmem_cache_free(ll_file_data_slab, fd);
-out:
- return rc;
-}
-
-int ll_size_lock(struct inode *inode, struct lov_stripe_md *lsm, obd_off start,
- int mode, struct lustre_handle **lockhs_p)
-{
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ldlm_extent extent;
- struct lustre_handle *lockhs = NULL;
- int rc, flags = 0, stripe_count;
- ENTRY;
-
- if (sbi->ll_flags & LL_SBI_NOLCK) {
- *lockhs_p = NULL;
- RETURN(0);
- }
-
- stripe_count = lsm->lsm_stripe_count;
- if (!stripe_count)
- stripe_count = 1;
-
- OBD_ALLOC(lockhs, stripe_count * sizeof(*lockhs));
- if (lockhs == NULL)
- RETURN(-ENOMEM);
-
- extent.start = start;
- extent.end = OBD_OBJECT_EOF;
-
- rc = obd_enqueue(&sbi->ll_osc_conn, lsm, NULL, LDLM_EXTENT, &extent,
- sizeof(extent), mode, &flags, ll_lock_callback,
- inode, sizeof(*inode), lockhs);
- if (rc != ELDLM_OK) {
- CERROR("lock enqueue: %d\n", rc);
- OBD_FREE(lockhs, stripe_count * sizeof(*lockhs));
- } else
- *lockhs_p = lockhs;
- RETURN(rc);
-}
-
-int ll_size_unlock(struct inode *inode, struct lov_stripe_md *lsm, int mode,
- struct lustre_handle *lockhs)
-{
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- int rc, stripe_count;
- ENTRY;
-
- if (sbi->ll_flags & LL_SBI_NOLCK)
- RETURN(0);
-
- if (lockhs == NULL) {
- LBUG();
- RETURN(-EINVAL);
- }
-
- rc = obd_cancel(&sbi->ll_osc_conn, lsm, mode, lockhs);
- if (rc != ELDLM_OK) {
- CERROR("lock cancel: %d\n", rc);
- LBUG();
- }
-
- stripe_count = lsm->lsm_stripe_count;
- if (!stripe_count)
- stripe_count = 1;
-
- OBD_FREE(lockhs, stripe_count * sizeof(*lockhs));
- RETURN(rc);
-}
-
-int ll_file_size(struct inode *inode, struct lov_stripe_md *lsm)
-{
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct lustre_handle *lockhs;
- struct obdo oa;
- int err, rc;
- ENTRY;
-
- LASSERT(lsm);
- LASSERT(sbi);
-
- rc = ll_size_lock(inode, lsm, 0, LCK_PR, &lockhs);
- if (rc != ELDLM_OK) {
- CERROR("lock enqueue: %d\n", rc);
- RETURN(rc);
- }
-
- oa.o_id = lsm->lsm_object_id;
- oa.o_mode = S_IFREG;
- oa.o_valid = OBD_MD_FLID|OBD_MD_FLTYPE|OBD_MD_FLSIZE|OBD_MD_FLBLOCKS;
- rc = obd_getattr(&sbi->ll_osc_conn, &oa, lsm);
- if (!rc)
- obdo_to_inode(inode, &oa,
- oa.o_valid & ~(OBD_MD_FLTYPE | OBD_MD_FLMODE));
-
- err = ll_size_unlock(inode, lsm, LCK_PR, lockhs);
- if (err != ELDLM_OK) {
- CERROR("lock cancel: %d\n", err);
- LBUG();
- }
- RETURN(rc);
-}
-
-static int ll_file_release(struct inode *inode, struct file *file)
-{
- struct ptlrpc_request *req = NULL;
- struct ll_file_data *fd;
- struct obdo oa;
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ll_inode_info *lli = ll_i2info(inode);
- struct lov_stripe_md *lsm = lli->lli_smd;
- int rc, rc2;
-
- ENTRY;
-
- fd = (struct ll_file_data *)file->private_data;
- if (!fd) {
- LASSERT(file->f_flags & O_LOV_DELAY_CREATE);
- GOTO(out, rc = 0);
- }
-
- memset(&oa, 0, sizeof(oa));
- oa.o_id = lsm->lsm_object_id;
- oa.o_mode = S_IFREG;
- oa.o_valid = OBD_MD_FLTYPE | OBD_MD_FLID;
- obd_handle2oa(&oa, &fd->fd_osthandle);
- rc = obd_close(ll_i2obdconn(inode), &oa, lsm);
- if (rc)
- GOTO(out_mdc, rc = -abs(rc));
-
-#if 0
-#error "This should only be done on the node that already has the EOF lock"
-#error "and only in the case where the file size actually changed. For now"
-#error "we don't care about the size on the MDS, since we never use it (the"
-#error "OST always has the authoritative size and we don't even use the MDS."
- /* If this fails and we goto out_fd, the file size on the MDS is out of
- * date. Is that a big deal? */
- if (file->f_mode & FMODE_WRITE) {
- struct lustre_handle *lockhs;
-
- rc = ll_size_lock(inode, lsm, 0, LCK_PR, &lockhs);
- if (rc)
- GOTO(out_mdc, -abs(rc));
-
- oa.o_id = lsm->lsm_object_id;
- oa.o_mode = S_IFREG;
- oa.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLSIZE |
- OBD_MD_FLBLOCKS;
- rc = obd_getattr(&sbi->ll_osc_conn, &oa, lsm);
- if (!rc) {
- struct iattr attr;
- attr.ia_valid = (ATTR_MTIME | ATTR_CTIME | ATTR_ATIME |
- ATTR_SIZE);
- attr.ia_mtime = inode->i_mtime;
- attr.ia_ctime = inode->i_ctime;
- attr.ia_atime = inode->i_atime;
- attr.ia_size = oa.o_size;
-
- inode->i_blocks = oa.o_blocks;
-
- /* XXX: this introduces a small race that we should
- * evaluate */
- rc = ll_inode_setattr(inode, &attr, 0);
- }
- rc2 = ll_size_unlock(inode, lli->lli_smd, LCK_PR, lockhs);
- if (rc2) {
- CERROR("lock cancel: %d\n", rc);
- LBUG();
- if (!rc)
- rc = rc2;
- }
- }
-#endif
-
-out_mdc:
- rc2 = mdc_close(&sbi->ll_mdc_conn, inode->i_ino,
- S_IFREG, &fd->fd_mdshandle, &req);
- ptlrpc_req_finished(req);
- if (rc2) {
- if (!rc)
- rc = -abs(rc2);
- GOTO(out_fd, rc);
- }
- DEBUG_REQ(D_HA, fd->fd_req, "matched open for this close: ");
- ptlrpc_req_finished(fd->fd_req);
-
- if (atomic_dec_and_test(&lli->lli_open_count)) {
- CDEBUG(D_INFO, "last close, cancelling unused locks\n");
- rc = obd_cancel_unused(ll_i2obdconn(inode), lsm, 0);
- if (rc)
- CERROR("obd_cancel_unused: %d\n", rc);
- } else {
- CDEBUG(D_INFO, "not last close, not cancelling unused locks\n");
- }
-
- EXIT;
-
-out_fd:
- fd->fd_mdshandle.cookie = DEAD_HANDLE_MAGIC;
- file->private_data = NULL;
- kmem_cache_free(ll_file_data_slab, fd);
-out:
- return rc;
-}
-
-static inline void ll_remove_suid(struct inode *inode)
-{
- unsigned int mode;
-
- /* set S_IGID if S_IXGRP is set, and always set S_ISUID */
- mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID;
-
- /* was any of the uid bits set? */
- mode &= inode->i_mode;
- if (mode && !capable(CAP_FSETID)) {
- inode->i_mode &= ~mode;
- // XXX careful here - we cannot change the size
- }
-}
-
-static void ll_update_atime(struct inode *inode)
-{
- struct iattr attr;
-
- attr.ia_atime = CURRENT_TIME;
- attr.ia_valid = ATTR_ATIME;
-
- if (inode->i_atime == attr.ia_atime) return;
- if (IS_RDONLY(inode)) return;
- if (IS_NOATIME(inode)) return;
-
- /* ll_inode_setattr() sets inode->i_atime from attr.ia_atime */
- ll_inode_setattr(inode, &attr, 0);
-}
-
-int ll_lock_callback(struct ldlm_lock *lock, struct ldlm_lock_desc *new,
- void *data, __u32 data_len, int flag)
-{
- struct inode *inode = data;
- struct lustre_handle lockh;
- int rc;
- ENTRY;
-
- if (data_len != sizeof(struct inode))
- LBUG();
-
- if (inode == NULL)
- LBUG();
-
- switch (flag) {
- case LDLM_CB_BLOCKING:
- ldlm_lock2handle(lock, &lockh);
- rc = ldlm_cli_cancel(&lockh);
- if (rc != ELDLM_OK)
- CERROR("ldlm_cli_cancel failed: %d\n", rc);
- break;
- case LDLM_CB_CANCELING:
- CDEBUG(D_INODE, "invalidating obdo/inode %ld\n", inode->i_ino);
- /* FIXME: do something better than throwing away everything */
- //down(&inode->i_sem);
- ll_invalidate_inode_pages(inode);
- //up(&inode->i_sem);
- break;
- default:
- LBUG();
- }
-
- RETURN(0);
-}
-
-static ssize_t ll_file_read(struct file *filp, char *buf, size_t count,
- loff_t *ppos)
-{
- struct ll_file_data *fd = (struct ll_file_data *)filp->private_data;
- struct inode *inode = filp->f_dentry->d_inode;
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct lustre_handle *lockhs = NULL;
- struct lov_stripe_md *lsm = ll_i2info(inode)->lli_smd;
- int flags = 0;
- ldlm_error_t err;
- ssize_t retval;
- ENTRY;
-
- /* If we don't refresh the file size, generic_file_read may not even
- * call us */
- retval = ll_file_size(inode, lsm);
- if (retval < 0) {
- CERROR("ll_file_size: %d\n", retval);
- RETURN(retval);
- }
-
- if (!(fd->fd_flags & LL_FILE_IGNORE_LOCK) &&
- !(sbi->ll_flags & LL_SBI_NOLCK)) {
- struct ldlm_extent extent;
- OBD_ALLOC(lockhs, lsm->lsm_stripe_count * sizeof(*lockhs));
- if (!lockhs)
- RETURN(-ENOMEM);
-
- extent.start = *ppos;
- extent.end = *ppos + count;
- CDEBUG(D_INFO, "Locking inode %ld, start "LPU64" end "LPU64"\n",
- inode->i_ino, extent.start, extent.end);
-
- err = obd_enqueue(&sbi->ll_osc_conn, lsm, NULL, LDLM_EXTENT,
- &extent, sizeof(extent), LCK_PR, &flags,
- ll_lock_callback, inode, sizeof(*inode),
- lockhs);
- if (err != ELDLM_OK) {
- OBD_FREE(lockhs, lsm->lsm_stripe_count*sizeof(*lockhs));
- CERROR("lock enqueue: err: %d\n", err);
- RETURN(err);
- }
- }
-
- CDEBUG(D_INFO, "Reading inode %ld, %d bytes, offset %Ld\n",
- inode->i_ino, count, *ppos);
- retval = generic_file_read(filp, buf, count, ppos);
-
- if (retval > 0)
- ll_update_atime(inode);
-
- if (!(fd->fd_flags & LL_FILE_IGNORE_LOCK) &&
- !(sbi->ll_flags & LL_SBI_NOLCK)) {
- err = obd_cancel(&sbi->ll_osc_conn, lsm, LCK_PR, lockhs);
- if (err != ELDLM_OK) {
- CERROR("lock cancel: err: %d\n", err);
- retval = err;
- }
- }
-
- if (lockhs)
- OBD_FREE(lockhs, lsm->lsm_stripe_count * sizeof(*lockhs));
- RETURN(retval);
-}
-
-/*
- * Write to a file (through the page cache).
- */
-static ssize_t
-ll_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- struct ll_file_data *fd = (struct ll_file_data *)file->private_data;
- struct inode *inode = file->f_dentry->d_inode;
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct lustre_handle *lockhs = NULL, *eof_lockhs = NULL;
- struct lov_stripe_md *lsm = ll_i2info(inode)->lli_smd;
- int flags = 0;
- ldlm_error_t err;
- ssize_t retval;
- ENTRY;
-
- if (!S_ISBLK(inode->i_mode) && file->f_flags & O_APPEND) {
- struct obdo *oa;
-
- oa = obdo_alloc();
- if (!oa)
- RETURN(-ENOMEM);
-
- err = ll_size_lock(inode, lsm, 0, LCK_PW, &eof_lockhs);
- if (err) {
- obdo_free(oa);
- RETURN(err);
- }
-
- oa->o_id = lsm->lsm_object_id;
- oa->o_mode = inode->i_mode;
- oa->o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLSIZE |
- OBD_MD_FLBLOCKS;
- obd_handle2oa(oa, &fd->fd_osthandle);
- retval = obd_getattr(&sbi->ll_osc_conn, oa, lsm);
- if (retval) {
- obdo_free(oa);
- GOTO(out_eof, retval);
- }
-
- *ppos = oa->o_size;
- obdo_to_inode(inode, oa, oa->o_valid);
- obdo_free(oa);
- }
-
- if (!(fd->fd_flags & LL_FILE_IGNORE_LOCK) &&
- !(sbi->ll_flags & LL_SBI_NOLCK)) {
- struct ldlm_extent extent;
- OBD_ALLOC(lockhs, lsm->lsm_stripe_count * sizeof(*lockhs));
- if (!lockhs)
- GOTO(out_eof, retval = -ENOMEM);
- extent.start = *ppos;
- extent.end = *ppos + count;
- CDEBUG(D_INFO, "Locking inode %ld, start "LPU64" end "LPU64"\n",
- inode->i_ino, extent.start, extent.end);
-
- err = obd_enqueue(&sbi->ll_osc_conn, lsm, NULL, LDLM_EXTENT,
- &extent, sizeof(extent), LCK_PW, &flags,
- ll_lock_callback, inode, sizeof(*inode),
- lockhs);
- if (err != ELDLM_OK) {
- CERROR("lock enqueue: err: %d\n", err);
- GOTO(out_free, retval = err);
- }
- }
-
- CDEBUG(D_INFO, "Writing inode %ld, %ld bytes, offset "LPD64"\n",
- inode->i_ino, (long)count, *ppos);
-
- retval = generic_file_write(file, buf, count, ppos);
-
- if (!(fd->fd_flags & LL_FILE_IGNORE_LOCK) ||
- sbi->ll_flags & LL_SBI_NOLCK) {
- err = obd_cancel(&sbi->ll_osc_conn, lsm, LCK_PW, lockhs);
- if (err != ELDLM_OK) {
- CERROR("lock cancel: err: %d\n", err);
- GOTO(out_free, retval = err);
- }
- }
-
- EXIT;
- out_free:
- if (lockhs)
- OBD_FREE(lockhs, lsm->lsm_stripe_count * sizeof(*lockhs));
-
- out_eof:
- if (!S_ISBLK(inode->i_mode) && file->f_flags & O_APPEND) {
- err = ll_size_unlock(inode, lsm, LCK_PW, eof_lockhs);
- if (err && !retval)
- retval = err;
- }
-
- return retval;
-}
-
-/* Retrieve object striping information.
- *
- * @arg is a pointer to a user struct with one or more of the fields set to
- * indicate the application preference: lmm_stripe_count, lmm_stripe_size,
- * lmm_stripe_offset, and lmm_stripe_pattern. lmm_magic must be LOV_MAGIC.
- */
-static int ll_lov_setstripe(struct inode *inode, struct file *file,
- unsigned long arg)
-{
- struct ll_inode_info *lli = ll_i2info(inode);
- struct lov_mds_md *lmm = NULL, *lmmu = (void *)arg;
- struct lustre_handle *conn = ll_i2obdconn(inode);
- int rc;
-
- rc = obd_alloc_wiremd(conn, &lmm);
- if (rc < 0)
- RETURN(rc);
-
- rc = copy_from_user(lmm, lmmu, sizeof(*lmm));
- if (rc)
- GOTO(out_free, rc = -EFAULT);
-
- if (lmm->lmm_magic != LOV_MAGIC) {
- CERROR("bad LOV magic %X\n", lmm->lmm_magic);
- GOTO(out_free, rc = -EINVAL);
- }
-
- down(&lli->lli_open_sem);
- if (lli->lli_smd) {
- CERROR("striping data already set for %d\n", inode->i_ino);
- GOTO(out_lov_up, rc = -EPERM);
- }
- rc = obd_unpackmd(conn, &lli->lli_smd, lmm);
- if (rc < 0) {
- CERROR("error setting LOV striping on %d: rc = %d\n",
- inode->i_ino, rc);
- GOTO(out_lov_up, rc);
- }
-
- rc = ll_create_objects(inode->i_sb, inode->i_ino, 0, 0, &lli->lli_smd);
- if (rc) {
- obd_free_memmd(conn, &lli->lli_smd);
- } else {
- file->f_flags &= ~O_LOV_DELAY_CREATE;
- rc = ll_file_open(inode, file);
- }
-out_lov_up:
- up(&lli->lli_open_sem);
-out_free:
- obd_free_wiremd(conn, &lmm);
- return rc;
-}
-
-/* Retrieve object striping information.
- *
- * @arg is a pointer to a user struct with lmm_ost_count indicating
- * the maximum number of OST indices which will fit in the user buffer.
- * lmm_magic must be LOV_MAGIC.
- */
-static int ll_lov_getstripe(struct inode *inode, unsigned long arg)
-{
- struct lov_mds_md lmm, *lmmu = (void *)arg, *lmmk = NULL;
- struct lov_stripe_md *lsm = ll_i2info(inode)->lli_smd;
- struct lustre_handle *conn = ll_i2obdconn(inode);
- int ost_count, rc, lmm_size;
-
- if (!lsm)
- RETURN(-ENODATA);
-
- rc = copy_from_user(&lmm, lmmu, sizeof(lmm));
- if (rc)
- RETURN(-EFAULT);
-
- if (lmm.lmm_magic != LOV_MAGIC)
- RETURN(-EINVAL);
-
- if (lsm->lsm_stripe_count == 0)
- ost_count = 1;
- else {
- struct obd_device *obd = class_conn2obd(conn);
- struct lov_obd *lov = &obd->u.lov;
- ost_count = lov->desc.ld_tgt_count;
- }
-
- /* XXX we _could_ check if indices > user lmm_ost_count are zero */
- if (lmm.lmm_ost_count < ost_count)
- RETURN(-EOVERFLOW);
-
- rc = obd_packmd(conn, &lmmk, lsm);
- if (rc < 0)
- RETURN(rc);
-
- lmm_size = rc;
-
- /* LOV STACKING layering violation to make LOV/OSC return same data */
- if (lsm->lsm_stripe_count == 0) {
- struct lov_object_id *loi;
-
- loi = (void *)lmmu + offsetof(typeof(*lmmu), lmm_objects);
- rc = copy_to_user(loi, &lsm->lsm_object_id, sizeof(*loi));
- if (rc) {
- lmm_size = 0;
- rc = -EFAULT;
- } else {
- lmmk->lmm_magic = LOV_MAGIC;
- lmmk->lmm_ost_count = lmmk->lmm_stripe_count = 1;
- }
- }
-
- if (lmm_size && copy_to_user(lmmu, lmmk, lmm_size))
- rc = -EFAULT;
-
- obd_free_wiremd(conn, &lmmk);
-
- RETURN(rc);
-}
-
-int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct ll_file_data *fd = (struct ll_file_data *)file->private_data;
- struct lustre_handle *conn;
- int flags;
-
- switch(cmd) {
- case LL_IOC_GETFLAGS:
- /* Get the current value of the file flags */
- return put_user(fd->fd_flags, (int *)arg);
- case LL_IOC_SETFLAGS:
- case LL_IOC_CLRFLAGS:
- /* Set or clear specific file flags */
- /* XXX This probably needs checks to ensure the flags are
- * not abused, and to handle any flag side effects.
- */
- if (get_user(flags, (int *) arg))
- return -EFAULT;
-
- if (cmd == LL_IOC_SETFLAGS)
- fd->fd_flags |= flags;
- else
- fd->fd_flags &= ~flags;
- return 0;
- case LL_IOC_LOV_SETSTRIPE:
- return ll_lov_setstripe(inode, file, arg);
- case LL_IOC_LOV_GETSTRIPE:
- return ll_lov_getstripe(inode, arg);
-
- /* We need to special case any other ioctls we want to handle,
- * to send them to the MDS/OST as appropriate and to properly
- * network encode the arg field.
- case EXT2_IOC_GETFLAGS:
- case EXT2_IOC_SETFLAGS:
- case EXT2_IOC_GETVERSION_OLD:
- case EXT2_IOC_GETVERSION_NEW:
- case EXT2_IOC_SETVERSION_OLD:
- case EXT2_IOC_SETVERSION_NEW:
- */
- default:
- conn = ll_i2obdconn(inode);
- return obd_iocontrol(cmd, conn, 0, NULL, (void *)arg);
- }
-}
-
-loff_t ll_file_seek(struct file *file, loff_t offset, int origin)
-{
- struct inode *inode = file->f_dentry->d_inode;
- long long retval;
- ENTRY;
-
- switch (origin) {
- case 2: {
- struct ll_inode_info *lli = ll_i2info(inode);
-
- retval = ll_file_size(inode, lli->lli_smd);
- if (retval)
- RETURN(retval);
-
- offset += inode->i_size;
- break;
- }
- case 1:
- offset += file->f_pos;
- }
- retval = -EINVAL;
- if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) {
- if (offset != file->f_pos) {
- file->f_pos = offset;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- file->f_reada = 0;
-#endif
- file->f_version = ++event;
- }
- retval = offset;
- }
- RETURN(retval);
-}
-
-/* XXX this does not need to do anything for data, it _does_ need to
- call setattr */
-int ll_fsync(struct file *file, struct dentry *dentry, int data)
-{
- return 0;
-}
-
-
-
-static int ll_inode_revalidate(struct dentry *dentry)
-{
- struct inode *inode = dentry->d_inode;
- struct lov_stripe_md *lsm;
- ENTRY;
-
- if (!inode)
- RETURN(0);
-
- lsm = ll_i2info(inode)->lli_smd;
- if (!lsm) /* object not yet allocated, don't validate size */
- RETURN(0);
-
- RETURN(ll_file_size(inode, lsm));
-}
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
-static int ll_getattr(struct vfsmount *mnt, struct dentry *de,
- struct kstat *stat)
-{
- return ll_inode_revalidate(de);
-}
-#endif
-
-struct file_operations ll_file_operations = {
- read: ll_file_read,
- write: ll_file_write,
- ioctl: ll_file_ioctl,
- open: ll_file_open,
- release: ll_file_release,
- mmap: generic_file_mmap,
- llseek: ll_file_seek,
- fsync: NULL
-};
-
-struct inode_operations ll_file_inode_operations = {
- setattr: ll_setattr,
- truncate: ll_truncate,
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
- getattr: ll_getattr,
-#else
- revalidate: ll_inode_revalidate,
-#endif
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-
-int rd_path(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_fstype(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct super_block *sb = (struct super_block*)data;
-
- len += snprintf(page, count, "%s\n", sb->s_type->name);
- return len;
-}
-
-int rd_blksize(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct super_block *sb = (struct super_block*)data;
- struct statfs mystats;
-
- (sb->s_op->statfs)(sb, &mystats);
- len += snprintf(page, count, "%lu\n", mystats.f_bsize);
- return len;
-
-}
-
-int rd_kbytestotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct super_block *sb = (struct super_block*)data;
- struct statfs mystats;
- __u32 blk_size;
- __u64 result;
-
- (sb->s_op->statfs)(sb, &mystats);
- blk_size = mystats.f_bsize;
- blk_size >>= 10;
- result = mystats.f_blocks;
-
- while(blk_size >>= 1)
- result <<= 1;
-
- len += snprintf(page, count, LPU64"\n", result);
- return len;
-}
-
-
-int rd_kbytesfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct super_block *sb = (struct super_block*)data;
- struct statfs mystats;
- __u32 blk_size;
- __u64 result;
-
- (sb->s_op->statfs)(sb, &mystats);
- blk_size = mystats.f_bsize;
- blk_size >>= 10;
- result = mystats.f_bfree;
-
- while(blk_size >>= 1)
- result <<= 1;
-
- len += snprintf(page, count, LPU64"\n", result);
- return len;
-}
-
-int rd_filestotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct super_block *sb = (struct super_block*)data;
- struct statfs mystats;
-
- (sb->s_op->statfs)(sb, &mystats);
- len += snprintf(page, count, LPU64"\n", (__u64)(mystats.f_files));
- return len;
-}
-
-int rd_filesfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct super_block *sb = (struct super_block*)data;
- struct statfs mystats;
-
- (sb->s_op->statfs)(sb, &mystats);
- len += snprintf(page, count, LPU64"\n", (__u64)(mystats.f_ffree));
- return len;
-}
-
-int rd_filegroups(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-int rd_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct super_block *sb = (struct super_block*)data;
- struct ll_sb_info *sbi = ll_s2sbi(sb);
-
- len += snprintf(page, count, "%s\n", sbi->ll_sb_uuid);
-
- return len;
-
-}
-int rd_dev_name(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct obd_device* dev = (struct obd_device*)data;
- len += snprintf(page, count, "%s\n", dev->obd_name);
- return len;
-}
-
-int rd_dev_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct obd_device* dev = (struct obd_device*)data;
- len += snprintf(page, count, "%s\n", dev->obd_uuid);
- return len;
-}
-
-
-struct lprocfs_vars status_var_nm_1[] = {
- {"status/uuid", rd_uuid, 0, 0},
- {"status/mntpt_path", rd_path, 0, 0},
- {"status/fstype", rd_fstype, 0, 0},
- {"status/blocksize",rd_blksize, 0, 0},
- {"status/kbytestotal",rd_kbytestotal, 0, 0},
- {"status/kbytesfree", rd_kbytesfree, 0, 0},
- {"status/filestotal", rd_filestotal, 0, 0},
- {"status/filesfree", rd_filesfree, 0, 0},
- {"status/filegroups", rd_filegroups, 0, 0},
- {0}
-};
-
-/*
- * Proc registration function for Lustre
- * file system
- */
-
-
-#define MAX_STRING_SIZE 100
-void ll_proc_namespace(struct super_block* sb, char* osc, char* mdc)
-{
- char mnt_name[MAX_STRING_SIZE+1];
- char uuid_name[MAX_STRING_SIZE+1];
- struct lprocfs_vars d_vars[3];
- struct ll_sb_info *sbi = ll_s2sbi(sb);
- struct obd_device* obd;
- int err;
-
- /* Register this mount instance with LProcFS */
- snprintf(mnt_name, MAX_STRING_SIZE, "mount_%s", sbi->ll_sb_uuid);
- mnt_name[MAX_STRING_SIZE] = '\0';
- sbi->ll_proc_root = lprocfs_reg_mnt(mnt_name);
- if (sbi->ll_proc_root == NULL) {
- CDEBUG(D_OTHER, "Could not register FS");
- return;
- }
- /* Add the static configuration info */
- err = lprocfs_add_vars(sbi->ll_proc_root,status_var_nm_1, sb);
- if (err) {
- CDEBUG(D_OTHER, "Unable to add procfs variables\n");
- return;
- }
- /* MDC */
- obd = class_uuid2obd(mdc);
- snprintf(mnt_name, MAX_STRING_SIZE, "status/%s/common_name",
- obd->obd_type->typ_name);
- mnt_name[MAX_STRING_SIZE] = '\0';
- memset(d_vars, 0, sizeof(d_vars));
- d_vars[0].read_fptr = rd_dev_name;
- d_vars[0].write_fptr = NULL;
- d_vars[0].name = mnt_name;
- snprintf(uuid_name, MAX_STRING_SIZE, "status/%s/uuid",
- obd->obd_type->typ_name);
- uuid_name[MAX_STRING_SIZE] = '\0';
- d_vars[1].read_fptr = rd_dev_uuid;
- d_vars[1].write_fptr = NULL;
- d_vars[1].name = uuid_name;
-
- err = lprocfs_add_vars(sbi->ll_proc_root, d_vars, obd);
- if (err) {
- CDEBUG(D_OTHER, "Unable to add fs proc dynamic variables\n");
- return;
- }
- /* OSC or LOV*/
- obd = class_uuid2obd(osc);
-
- /* Reuse mnt_name */
- snprintf(mnt_name, MAX_STRING_SIZE,
- "status/%s/common_name", obd->obd_type->typ_name);
- mnt_name[MAX_STRING_SIZE] = '\0';
- memset(d_vars, 0, sizeof(d_vars));
- d_vars[0].read_fptr = rd_dev_name;
- d_vars[0].write_fptr = NULL;
- d_vars[0].name = mnt_name;
-
- snprintf(uuid_name, MAX_STRING_SIZE, "status/%s/uuid",
- obd->obd_type->typ_name);
- uuid_name[MAX_STRING_SIZE] = '\0';
- d_vars[1].read_fptr = rd_dev_uuid;
- d_vars[1].write_fptr = NULL;
- d_vars[1].name = uuid_name;
-
- err = lprocfs_add_vars(sbi->ll_proc_root, d_vars, obd);
- if (err) {
- CDEBUG(D_OTHER, "Unable to add fs proc dynamic variables\n");
- return;
- }
-}
-#undef MAX_STRING_SIZE
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copyright (C) 1992, 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * from
- *
- * linux/fs/ext2/namei.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * Big-endian to little-endian byte-swapping/bitmaps by
- * David S. Miller (davem@caip.rutgers.edu), 1995
- * Directory entry file type support and forward compatibility hooks
- * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
- *
- * Changes for use in OBDFS
- * Copyright (c) 1999, Seagate Technology Inc.
- * Copyright (C) 2001, Cluster File Systems, Inc.
- * Rewritten based on recent ext2 page cache use.
- *
- */
-
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp_lock.h>
-#include <linux/quotaops.h>
-#include <linux/highmem.h>
-#include <linux/pagemap.h>
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/obd_support.h>
-#include <linux/lustre_lite.h>
-#include <linux/lustre_dlm.h>
-
-extern struct address_space_operations ll_aops;
-
-/* from super.c */
-extern void ll_change_inode(struct inode *inode);
-extern int ll_setattr(struct dentry *de, struct iattr *attr);
-
-/* from dir.c */
-extern int ll_add_link (struct dentry *dentry, struct inode *inode);
-obd_id ll_inode_by_name(struct inode * dir, struct dentry *dentry, int *typ);
-int ext2_make_empty(struct inode *inode, struct inode *parent);
-struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
- struct dentry *dentry, struct page ** res_page);
-int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page );
-int ext2_empty_dir (struct inode * inode);
-struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p);
-void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
- struct page *page, struct inode *inode);
-
-/*
- * Couple of helper functions - make the code slightly cleaner.
- */
-static inline void ext2_inc_count(struct inode *inode)
-{
- inode->i_nlink++;
-}
-
-/* postpone the disk update until the inode really goes away */
-static inline void ext2_dec_count(struct inode *inode)
-{
- inode->i_nlink--;
-}
-static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
-{
- int err;
- err = ll_add_link(dentry, inode);
- if (!err) {
- d_instantiate(dentry, inode);
- return 0;
- }
- ext2_dec_count(inode);
- iput(inode);
- return err;
-}
-
-/* methods */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static int ll_find_inode(struct inode *inode, unsigned long ino, void *opaque)
-#else
-static int ll_test_inode(struct inode *inode, void *opaque)
-#endif
-{
- struct ll_read_inode2_cookie *lic = opaque;
- struct mds_body *body = lic->lic_body;
-
- if (inode->i_generation != lic->lic_body->generation)
- return 0;
-
- /* Apply the attributes in 'opaque' to this inode */
- ll_update_inode(inode, body);
-
- return 1;
-}
-
-extern struct dentry_operations ll_d_ops;
-
-int ll_unlock(__u32 mode, struct lustre_handle *lockh)
-{
- ENTRY;
-
- ldlm_lock_decref(lockh, mode);
-
- RETURN(0);
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
-extern int ll_read_inode2(struct inode *inode, void *opaque);
-struct inode *ll_iget(struct super_block *sb, ino_t hash,
- struct ll_read_inode2_cookie *lic)
-{
- struct inode *inode;
-
- LASSERT(hash != 0);
- inode = iget5_locked(sb, hash, ll_test_inode, ll_read_inode2, lic);
-
- if (!inode)
- return ERR_PTR(-ENOMEM);
-
- if (inode->i_state & I_NEW)
- unlock_new_inode(inode);
-
- // XXX Coda always fills inodes, should Lustre?
- return inode;
-}
-#else
-struct inode *ll_iget(struct super_block *sb, ino_t hash,
- struct ll_read_inode2_cookie *lic)
-{
- struct inode *inode;
- LASSERT(hash != 0);
- inode = iget4(sb, hash, ll_find_inode, lic);
- return inode;
-}
-#endif
-
-static int ll_intent_to_lock_mode(struct lookup_intent *it)
-{
- /* CREAT needs to be tested before open (both could be set) */
- if ((it->it_op & (IT_CREAT | IT_MKDIR | IT_SETATTR | IT_MKNOD))) {
- return LCK_PW;
- } else if (it->it_op & (IT_READDIR | IT_GETATTR | IT_OPEN | IT_UNLINK |
- IT_RMDIR | IT_RENAME | IT_RENAME2 | IT_READLINK|
- IT_LINK | IT_LINK2 | IT_LOOKUP | IT_SYMLINK)) {
- return LCK_PR;
- }
-
- LBUG();
- RETURN(-EINVAL);
-}
-
-#define LL_LOOKUP_POSITIVE 1
-#define LL_LOOKUP_NEGATIVE 2
-
-int ll_intent_lock(struct inode *parent, struct dentry **de,
- struct lookup_intent *it,
- intent_finish_cb intent_finish)
-{
- struct dentry *dentry = *de;
- struct ll_sb_info *sbi = ll_i2sbi(parent);
- struct lustre_handle lockh;
- struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
- struct ptlrpc_request *request = NULL;
- char *data = NULL;
- int rc, lock_mode, datalen = 0, offset, flag = LL_LOOKUP_POSITIVE;
- obd_id ino = 0;
-
- ENTRY;
-
- if (it == NULL)
- it = &lookup_it;
-
- CDEBUG(D_INFO, "name: %*s, intent: %s\n", dentry->d_name.len,
- dentry->d_name.name, ldlm_it2str(it->it_op));
-
- if (dentry->d_name.len > EXT2_NAME_LEN)
- RETURN(-ENAMETOOLONG);
-
- lock_mode = ll_intent_to_lock_mode(it);
- if (it->it_op & IT_SYMLINK) {
- data = it->it_data;
- datalen = strlen(data) + 1;
- it->it_data = NULL;
- }
-
- rc = mdc_enqueue(&sbi->ll_mdc_conn, LDLM_PLAIN, it, lock_mode, parent,
- dentry, &lockh, data, datalen, parent,sizeof(*parent));
- if (rc < 0)
- RETURN(rc);
- memcpy(it->it_lock_handle, &lockh, sizeof(lockh));
-
- request = (struct ptlrpc_request *)it->it_data;
- /* it_disposition == 1 indicates that the server performed the
- * intent on our behalf. */
- if (it->it_disposition) {
- struct mds_body *mds_body;
- int mode;
- obd_flag valid;
-
- /* This long block is all about fixing up the local
- * state so that it is correct as of the moment
- * _before_ the operation was applied; that way, the
- * VFS will think that everything is normal and call
- * Lustre's regular FS function.
- *
- * If we're performing a creation, that means that unless the
- * creation failed with EEXIST, we should fake up a negative
- * dentry. Likewise for the target of a hard link.
- *
- * For everything else, we want to lookup to succeed. */
-
- /* One additional note: if CREATE/MKDIR/etc succeeded,
- * we add an extra reference to the request because we
- * need to keep it around until ll_create gets called.
- * For anything else which results in
- * LL_LOOKUP_POSITIVE, we can do the iget()
- * immediately with the contents of the reply (in the
- * intent_finish callback). In the create case,
- * however, we need to wait until ll_create_node to do
- * the iget() or the VFS will abort with -EEXISTS.
- */
-
- offset = 1;
- mds_body = lustre_msg_buf(request->rq_repmsg, offset);
- ino = mds_body->fid1.id;
- mode = mds_body->mode;
-
- if (it->it_op & (IT_CREAT | IT_MKDIR | IT_SYMLINK | IT_MKNOD)) {
- mdc_store_inode_generation(request, 2, 1);
- /* For create ops, we want the lookup to be negative,
- * unless the create failed in a way that indicates
- * that the file is already there */
- if (it->it_status == 0)
- atomic_inc(&request->rq_refcount);
- if (it->it_status != -EEXIST)
- GOTO(out, flag = LL_LOOKUP_NEGATIVE);
- /*
- * Fall through to update attibutes: it may already
- * have appeared in the namespace of another client
- */
- } else if (it->it_op & (IT_GETATTR | IT_SETATTR | IT_LOOKUP |
- IT_READLINK)) {
- /* For check ops, we want the lookup to succeed */
- it->it_data = NULL;
- if (it->it_status)
- GOTO(out, flag = LL_LOOKUP_NEGATIVE);
- /* Fall through to update attibutes. */
- } else if (it->it_op & (IT_RENAME | IT_LINK)) {
- /* For rename, we want the source lookup to succeed */
- if (it->it_status) {
- it->it_data = NULL;
- GOTO(drop_req, rc = it->it_status);
- }
- /* Fall through to update attibutes. */
- } else if (it->it_op & (IT_UNLINK | IT_RMDIR)) {
- /* For remove ops, we want the lookup to succeed unless
- * the file truly doesn't exist */
- it->it_data = NULL;
- if (it->it_status == -ENOENT)
- GOTO(out, flag = LL_LOOKUP_NEGATIVE);
- /* No point in updating attributes that we're about to
- * unlink. -phil */
- GOTO(out, flag = LL_LOOKUP_POSITIVE);
- } else if (it->it_op == IT_OPEN) {
- it->it_data = NULL;
- if (it->it_status && it->it_status != -EEXIST)
- GOTO(out, flag = LL_LOOKUP_NEGATIVE);
- /* Fall through to update attibutes. */
- } else if (it->it_op & (IT_RENAME2 | IT_LINK2)) {
- it->it_data = NULL;
- /* This means the target lookup is negative */
- if (mds_body->valid == 0)
- GOTO(out, flag = LL_LOOKUP_NEGATIVE);
- /* XXX bug 289: should we maybe fall through here? -p */
- GOTO(out, flag = LL_LOOKUP_POSITIVE);
- }
-
- /* Do a getattr now that we have the lock */
- valid = OBD_MD_FLNOTOBD;
- if (it->it_op == IT_READLINK) {
- datalen = mds_body->size;
- valid |= OBD_MD_LINKNAME;
- } else if (S_ISREG(mode)) {
- datalen = obd_size_wiremd(&sbi->ll_osc_conn, NULL);
- valid |= OBD_MD_FLEASIZE;
- }
- ptlrpc_req_finished(request);
- request = NULL;
- rc = mdc_getattr(&sbi->ll_mdc_conn, ino, mode,
- valid, datalen, &request);
- if (rc) {
- CERROR("failure %d inode "LPX64"\n", rc, ino);
- GOTO(drop_req, rc = -abs(rc));
- }
- offset = 0;
- } else {
- obd_flag valid;
- int mode;
-
- LBUG(); /* For the moment, no non-intent locks */
-
- /* it_disposition == 0 indicates that it just did a simple lock
- * request, for which we are very thankful. move along with
- * the local lookup then. */
-
- //memcpy(&lli->lli_intent_lock_handle, &lockh, sizeof(lockh));
- offset = 0;
-
- ino = ll_inode_by_name(parent, dentry, &mode);
- if (!ino) {
- CERROR("inode %*s not found by name\n",
- dentry->d_name.len, dentry->d_name.name);
- GOTO(drop_lock, rc = -ENOENT);
- }
-
- valid = OBD_MD_FLNOTOBD;
-
- if (S_ISREG(mode)) {
- datalen = obd_size_wiremd(&sbi->ll_osc_conn, NULL),
- valid |= OBD_MD_FLEASIZE;
- }
-
- rc = mdc_getattr(&sbi->ll_mdc_conn, ino, mode, valid,
- datalen, &request);
- if (rc) {
- CERROR("failure %d inode "LPX64"\n", rc, ino);
- GOTO(drop_req, rc = -abs(rc));
- }
- }
-
- EXIT;
- out:
- if (intent_finish != NULL) {
- rc = intent_finish(flag, request, de, it, offset, ino);
- dentry = *de; /* intent_finish may change *de */
- } else {
- ptlrpc_req_finished(request);
- }
-
- if (it->it_disposition && it->it_op & (IT_RENAME | IT_LINK))
- it->it_data = dentry;
-
- /* this places the intent in the dentry so that the vfs_xxx
- * operation can lay its hands on it; but that is not
- * always needed...
- */
- if ( // it->it_status == 0 &&
- it->it_op != IT_RENAME2 &&
- it->it_op != IT_SETATTR &&
- it->it_op != IT_GETATTR &&
- it->it_op != IT_READDIR &&
- it->it_op != IT_LOOKUP) {
- LL_SAVE_INTENT(dentry, it);
- } else {
- CDEBUG(D_DENTRY,
- "D_IT dentry %p fsdata %p intent: %s status %d\n",
- dentry, ll_d2d(dentry), ldlm_it2str(it->it_op),
- it->it_status);
- }
-
- if (rc < 0 || it->it_op == IT_LOOKUP)
- ll_intent_release(dentry, it);
-
- RETURN(rc);
-
- drop_req:
- ptlrpc_free_req(request);
- drop_lock:
-#warning FIXME: must release lock here
- RETURN(rc);
-}
-
-/* Search "inode"'s alias list for a dentry that has the same name and parent as
- * de. If found, return it. If not found, return de. */
-struct dentry *ll_find_alias(struct inode *inode, struct dentry *de)
-{
- struct list_head *tmp;
-
- spin_lock(&dcache_lock);
- list_for_each(tmp, &inode->i_dentry) {
- struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
-
- /* We are called here with 'de' already on the aliases list. */
- if (dentry == de) {
- CERROR("whoops\n");
- continue;
- }
-
- if (dentry->d_parent != de->d_parent)
- continue;
-
- if (dentry->d_name.len != de->d_name.len)
- continue;
-
- if (memcmp(dentry->d_name.name, de->d_name.name,
- de->d_name.len) != 0)
- continue;
-
- if (!list_empty(&dentry->d_lru))
- list_del_init(&dentry->d_lru);
-
- list_del_init(&dentry->d_hash);
- spin_unlock(&dcache_lock);
- d_rehash(dentry);
- atomic_inc(&dentry->d_count);
- iput(inode);
- return dentry;
- }
-
- spin_unlock(&dcache_lock);
-
- return de;
-}
-
-static int
-lookup2_finish(int flag, struct ptlrpc_request *request, struct dentry **de,
- struct lookup_intent *it, int offset, obd_id ino)
-{
- struct dentry *dentry = *de, *saved = *de;
- struct inode *inode = NULL;
- struct ll_read_inode2_cookie lic = {.lic_body = NULL, .lic_lmm = NULL};
-
- if (flag == LL_LOOKUP_POSITIVE) {
- ENTRY;
- lic.lic_body = lustre_msg_buf(request->rq_repmsg, offset);
-
- if (S_ISREG(lic.lic_body->mode) &&
- lic.lic_body->valid & OBD_MD_FLEASIZE) {
- LASSERT(request->rq_repmsg->bufcount > offset);
- lic.lic_lmm = lustre_msg_buf(request->rq_repmsg,
- offset + 1);
- } else {
- lic.lic_lmm = NULL;
- }
-
- /* No rpc's happen during iget4, -ENOMEM's are possible */
- inode = ll_iget(dentry->d_sb, ino, &lic);
- if (!inode) {
- /* XXX make sure that request is freed in this case;
- * I think it is, but double-check refcounts. -phil */
- RETURN(-ENOMEM);
- }
-
- dentry = *de = ll_find_alias(inode, dentry);
-
- /* We asked for a lock on the directory, and may have been
- * granted a lock on the inode. Just in case, fixup the data
- * pointer. */
- ldlm_lock_set_data((struct lustre_handle *)it->it_lock_handle,
- inode, sizeof(*inode));
-
- EXIT;
- } else {
- ENTRY;
- }
-
- ptlrpc_req_finished(request);
-
- dentry->d_op = &ll_d_ops;
- if (ll_d2d(dentry) == NULL) {
- ll_set_dd(dentry);
- }
-
- if (dentry == saved)
- d_add(dentry, inode);
-
- RETURN(0);
-}
-
-static struct dentry *ll_lookup2(struct inode *parent, struct dentry *dentry,
- struct lookup_intent *it)
-{
- struct dentry *save = dentry;
- int rc;
-
- rc = ll_intent_lock(parent, &dentry, it, lookup2_finish);
- if (rc < 0) {
- CERROR("ll_intent_lock: %d\n", rc);
- return ERR_PTR(rc);
- }
-
- if (dentry == save)
- return NULL;
- else
- return dentry;
-}
-
-static struct inode *ll_create_node(struct inode *dir, const char *name,
- int namelen, const void *data, int datalen,
- int mode, __u64 extra,
- struct lookup_intent *it)
-{
- struct inode *inode;
- struct ptlrpc_request *request = NULL;
- struct mds_body *body;
- time_t time = CURRENT_TIME;
- struct ll_sb_info *sbi = ll_i2sbi(dir);
- struct ll_read_inode2_cookie lic = { .lic_lmm = NULL, };
- ENTRY;
-
- if (it && it->it_disposition) {
- int rc = it->it_status;
- if (rc) {
- CERROR("error creating MDS inode for %*s: rc = %d\n",
- namelen, name, rc);
- RETURN(ERR_PTR(rc));
- }
- ll_invalidate_inode_pages(dir);
- request = it->it_data;
- body = lustre_msg_buf(request->rq_repmsg, 1);
- } else {
- int gid = current->fsgid;
- int rc;
-
- if (dir->i_mode & S_ISGID) {
- gid = dir->i_gid;
- if (S_ISDIR(mode))
- mode |= S_ISGID;
- }
-
- rc = mdc_create(&sbi->ll_mdc_conn, dir, name, namelen,
- data, datalen, mode, current->fsuid, gid,
- time, extra, &request);
- if (rc) {
- inode = ERR_PTR(rc);
- GOTO(out, rc);
- }
- body = lustre_msg_buf(request->rq_repmsg, 0);
- }
-
- lic.lic_body = body;
-
- inode = ll_iget(dir->i_sb, body->ino, &lic);
- if (IS_ERR(inode)) {
- int rc = PTR_ERR(inode);
- CERROR("new_inode -fatal: rc %d\n", rc);
- LBUG();
- GOTO(out, rc);
- }
-
- if (!list_empty(&inode->i_dentry)) {
- CERROR("new_inode -fatal: inode %d, ct %d lnk %d\n",
- body->ino, atomic_read(&inode->i_count),
- inode->i_nlink);
- iput(inode);
- LBUG();
- inode = ERR_PTR(-EIO);
- GOTO(out, -EIO);
- }
-
- if (it && it->it_disposition) {
- /* We asked for a lock on the directory, but were
- * granted a lock on the inode. Since we finally have
- * an inode pointer, stuff it in the lock. */
- ldlm_lock_set_data((struct lustre_handle *)it->it_lock_handle,
- inode, sizeof(*inode));
- }
-
- EXIT;
- out:
- ptlrpc_req_finished(request);
- return inode;
-}
-
-static int ll_mdc_unlink(struct inode *dir, struct inode *child, __u32 mode,
- const char *name, int len)
-{
- struct ptlrpc_request *request = NULL;
- struct ll_sb_info *sbi = ll_i2sbi(dir);
- int err;
-
- ENTRY;
-
- err = mdc_unlink(&sbi->ll_mdc_conn, dir, child, mode, name, len,
- &request);
- ptlrpc_req_finished(request);
-
- RETURN(err);
-}
-
-int ll_mdc_link(struct dentry *src, struct inode *dir,
- const char *name, int len)
-{
- struct ptlrpc_request *request = NULL;
- int err;
- struct ll_sb_info *sbi = ll_i2sbi(dir);
-
- ENTRY;
-
- err = mdc_link(&sbi->ll_mdc_conn, src, dir, name, len, &request);
- ptlrpc_req_finished(request);
-
- RETURN(err);
-}
-
-int ll_mdc_rename(struct inode *src, struct inode *tgt,
- struct dentry *old, struct dentry *new)
-{
- struct ptlrpc_request *request = NULL;
- struct ll_sb_info *sbi = ll_i2sbi(src);
- int err;
-
- ENTRY;
-
- err = mdc_rename(&sbi->ll_mdc_conn, src, tgt,
- old->d_name.name, old->d_name.len,
- new->d_name.name, new->d_name.len, &request);
- ptlrpc_req_finished(request);
-
- RETURN(err);
-}
-
-/*
- * By the time this is called, we already have created the directory cache
- * entry for the new file, but it is so far negative - it has no inode.
- *
- * We defer creating the OBD object(s) until open, to keep the intent and
- * non-intent code paths similar, and also because we do not have the MDS
- * inode number before calling ll_create_node() (which is needed for LOV),
- * so we would need to do yet another RPC to the MDS to store the LOV EA
- * data on the MDS. If needed, we would pass the PACKED lmm as data and
- * lmm_size in datalen (the MDS still has code which will handle that).
- *
- * If the create succeeds, we fill in the inode information
- * with d_instantiate().
- */
-static int ll_create(struct inode *dir, struct dentry *dentry, int mode)
-{
- struct lookup_intent *it;
- struct inode *inode;
- int rc = 0;
- ENTRY;
-
- LL_GET_INTENT(dentry, it);
-
- inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
- NULL, 0, mode, 0, it);
-
- if (IS_ERR(inode))
- RETURN(PTR_ERR(inode));
-
- if (it && it->it_disposition) {
- d_instantiate(dentry, inode);
- } else {
- /* no directory data updates when intents rule */
- rc = ext2_add_nondir(dentry, inode);
- }
-
- RETURN(rc);
-}
-
-static int ll_mknod(struct inode *dir, struct dentry *dentry, int mode,
- int rdev)
-{
- struct lookup_intent *it;
- struct inode *inode;
- int rc = 0;
-
- LL_GET_INTENT(dentry, it);
-
- inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
- NULL, 0, mode, rdev, it);
-
- if (IS_ERR(inode))
- RETURN(PTR_ERR(inode));
-
- /* no directory data updates when intents rule */
- if (it && it->it_disposition)
- d_instantiate(dentry, inode);
- else
- rc = ext2_add_nondir(dentry, inode);
-
- return rc;
-}
-
-static int ll_symlink(struct inode *dir, struct dentry *dentry,
- const char *symname)
-{
- struct lookup_intent *it;
- unsigned l = strlen(symname) + 1;
- struct inode *inode;
- struct ll_inode_info *lli;
- int err = 0;
- ENTRY;
-
- LL_GET_INTENT(dentry, it);
-
- inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
- symname, l, S_IFLNK | S_IRWXUGO, 0, it);
- if (IS_ERR(inode))
- RETURN(PTR_ERR(inode));
-
- lli = ll_i2info(inode);
-
- OBD_ALLOC(lli->lli_symlink_name, l);
- /* this _could_ be a non-fatal error, since the symlink is already
- * stored on the MDS by this point, and we can re-get it in readlink.
- */
- if (!lli->lli_symlink_name)
- RETURN(-ENOMEM);
-
- memcpy(lli->lli_symlink_name, symname, l);
- inode->i_size = l - 1;
-
- /* no directory data updates when intents rule */
- if (it && it->it_disposition)
- d_instantiate(dentry, inode);
- else
- err = ext2_add_nondir(dentry, inode);
-
- RETURN(err);
-}
-
-static int ll_link(struct dentry *old_dentry, struct inode * dir,
- struct dentry *dentry)
-{
- struct lookup_intent *it;
- struct inode *inode = old_dentry->d_inode;
- int rc;
-
- LL_GET_INTENT(dentry, it);
-
- if (it && it->it_disposition) {
- if (it->it_status)
- RETURN(it->it_status);
- inode->i_ctime = CURRENT_TIME;
- ext2_inc_count(inode);
- atomic_inc(&inode->i_count);
- d_instantiate(dentry, inode);
- ll_invalidate_inode_pages(dir);
- RETURN(0);
- }
-
- if (S_ISDIR(inode->i_mode))
- return -EPERM;
-
- if (inode->i_nlink >= EXT2_LINK_MAX)
- return -EMLINK;
-
- rc = ll_mdc_link(old_dentry, dir,
- dentry->d_name.name, dentry->d_name.len);
- if (rc)
- RETURN(rc);
-
- inode->i_ctime = CURRENT_TIME;
- ext2_inc_count(inode);
- atomic_inc(&inode->i_count);
-
- return ext2_add_nondir(dentry, inode);
-}
-
-static int ll_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
- struct lookup_intent *it;
- struct inode * inode;
- int err = -EMLINK;
- ENTRY;
-
- LL_GET_INTENT(dentry, it);
-
- if (dir->i_nlink >= EXT2_LINK_MAX)
- goto out;
-
- ext2_inc_count(dir);
- inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
- NULL, 0, S_IFDIR | mode, 0, it);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_dir;
-
- err = ext2_make_empty(inode, dir);
- if (err)
- goto out_fail;
-
- /* no directory data updates when intents rule */
- if (!it || !it->it_disposition) {
- /* XXX FIXME This code needs re-checked for non-intents */
- ext2_inc_count(inode);
- err = ll_add_link(dentry, inode);
- if (err)
- goto out_fail;
- }
-
- d_instantiate(dentry, inode);
-out:
- EXIT;
- return err;
-
-out_fail:
- ext2_dec_count(inode);
- ext2_dec_count(inode);
- iput(inode);
- EXIT;
-out_dir:
- ext2_dec_count(dir);
- EXIT;
- goto out;
-}
-
-static int ll_common_unlink(struct inode *dir, struct dentry *dentry,
- struct lookup_intent *it, __u32 mode)
-{
- struct inode *inode = dentry->d_inode;
- struct ext2_dir_entry_2 * de;
- struct page * page;
- int rc = 0;
-
- if (it && it->it_disposition) {
- rc = it->it_status;
- ll_invalidate_inode_pages(dir);
- if (rc)
- GOTO(out, rc);
- GOTO(out_dec, 0);
- }
-
- de = ext2_find_entry(dir, dentry, &page);
- if (!de)
- GOTO(out, rc = -ENOENT);
- rc = ll_mdc_unlink(dir, dentry->d_inode, mode,
- dentry->d_name.name, dentry->d_name.len);
- if (rc)
- GOTO(out, rc);
-
- rc = ext2_delete_entry(de, page);
- if (rc)
- GOTO(out, rc);
-
- /* AED: not sure if needed - directory lock revocation should do it
- * in the case where the client has cached it for non-intent ops.
- */
- ll_invalidate_inode_pages(dir);
-
- inode->i_ctime = dir->i_ctime;
-out_dec:
- ext2_dec_count(inode);
-out:
- return rc;
-}
-
-static int ll_unlink(struct inode *dir, struct dentry *dentry)
-{
- struct lookup_intent * it;
-
- LL_GET_INTENT(dentry, it);
-
- return ll_common_unlink(dir, dentry, it, S_IFREG);
-}
-
-static int ll_rmdir(struct inode *dir, struct dentry *dentry)
-{
- struct inode * inode = dentry->d_inode;
- struct lookup_intent *it;
- int rc;
- ENTRY;
-
- LL_GET_INTENT(dentry, it);
-
- if ((!it || !it->it_disposition) && !ext2_empty_dir(inode))
- RETURN(-ENOTEMPTY);
-
- rc = ll_common_unlink(dir, dentry, it, S_IFDIR);
- if (!rc) {
- inode->i_size = 0;
- ext2_dec_count(inode);
- ext2_dec_count(dir);
- }
-
- RETURN(rc);
-}
-
-static int ll_rename(struct inode * old_dir, struct dentry * old_dentry,
- struct inode * new_dir, struct dentry * new_dentry)
-{
- struct lookup_intent *it;
- struct inode * old_inode = old_dentry->d_inode;
- struct inode * tgt_inode = new_dentry->d_inode;
- struct page * dir_page = NULL;
- struct ext2_dir_entry_2 * dir_de = NULL;
- struct ext2_dir_entry_2 * old_de;
- struct page * old_page;
- int err;
-
- LL_GET_INTENT(old_dentry, it);
-
- if (it && it->it_disposition) {
- if (tgt_inode) {
- tgt_inode->i_ctime = CURRENT_TIME;
- tgt_inode->i_nlink--;
- }
- ll_invalidate_inode_pages(old_dir);
- ll_invalidate_inode_pages(new_dir);
- GOTO(out, err = it->it_status);
- }
-
- err = ll_mdc_rename(old_dir, new_dir, old_dentry, new_dentry);
- if (err)
- goto out;
-
- old_de = ext2_find_entry (old_dir, old_dentry, &old_page);
- if (!old_de)
- goto out;
-
- if (S_ISDIR(old_inode->i_mode)) {
- err = -EIO;
- dir_de = ext2_dotdot(old_inode, &dir_page);
- if (!dir_de)
- goto out_old;
- }
-
- if (tgt_inode) {
- struct page *new_page;
- struct ext2_dir_entry_2 *new_de;
-
- err = -ENOTEMPTY;
- if (dir_de && !ext2_empty_dir (tgt_inode))
- goto out_dir;
-
- err = -ENOENT;
- new_de = ext2_find_entry (new_dir, new_dentry, &new_page);
- if (!new_de)
- goto out_dir;
- ext2_inc_count(old_inode);
- ext2_set_link(new_dir, new_de, new_page, old_inode);
- tgt_inode->i_ctime = CURRENT_TIME;
- if (dir_de)
- tgt_inode->i_nlink--;
- ext2_dec_count(tgt_inode);
- } else {
- if (dir_de) {
- err = -EMLINK;
- if (new_dir->i_nlink >= EXT2_LINK_MAX)
- goto out_dir;
- }
- ext2_inc_count(old_inode);
- err = ll_add_link(new_dentry, old_inode);
- if (err) {
- ext2_dec_count(old_inode);
- goto out_dir;
- }
- if (dir_de)
- ext2_inc_count(new_dir);
- }
-
- ext2_delete_entry (old_de, old_page);
- ext2_dec_count(old_inode);
-
- if (dir_de) {
- ext2_set_link(old_inode, dir_de, dir_page, new_dir);
- ext2_dec_count(old_dir);
- }
- return 0;
-
-out_dir:
- if (dir_de) {
- kunmap(dir_page);
- page_cache_release(dir_page);
- }
-out_old:
- kunmap(old_page);
- page_cache_release(old_page);
-out:
- return err;
-}
-
-struct inode_operations ll_dir_inode_operations = {
- create: ll_create,
- lookup2: ll_lookup2,
- link: ll_link,
- unlink: ll_unlink,
- symlink: ll_symlink,
- mkdir: ll_mkdir,
- rmdir: ll_rmdir,
- mknod: ll_mknod,
- rename: ll_rename,
- setattr: ll_setattr
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Lustre Lite recovery infrastructure.
- *
- * Copyright (C) 2002 Cluster File Systems Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_lite.h>
-#include <linux/lustre_ha.h>
-#include <linux/lustre_dlm.h>
-#include <linux/lustre_idl.h>
-
-static int ll_retry_recovery(struct ptlrpc_connection *conn)
-{
- ENTRY;
- RETURN(0);
-}
-
-int ll_recover(struct recovd_data *rd, int phase)
-{
- struct ptlrpc_connection *conn = class_rd2conn(rd);
- struct list_head *tmp;
-
- LASSERT(conn);
- ENTRY;
-
- switch (phase) {
- case PTLRPC_RECOVD_PHASE_PREPARE:
- case PTLRPC_RECOVD_PHASE_RECOVER:
- list_for_each(tmp, &conn->c_imports) {
- struct obd_import *imp =
- list_entry(tmp, struct obd_import, imp_chain);
-
- if (phase == PTLRPC_RECOVD_PHASE_PREPARE) {
- spin_lock(&imp->imp_lock);
- imp->imp_level = LUSTRE_CONN_RECOVD;
- spin_unlock(&imp->imp_lock);
- }
- imp->imp_recover(imp, phase);
- }
-
- if (phase == PTLRPC_RECOVD_PHASE_PREPARE)
- RETURN(ptlrpc_run_recovery_upcall(conn));
- RETURN(0);
-
- case PTLRPC_RECOVD_PHASE_FAILURE:
- RETURN(ll_retry_recovery(conn));
- }
-
- LBUG();
- RETURN(-ENOSYS);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Lustre Lite I/O Page Cache
- *
- * Copyright (c) 2001, 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/iobuf.h>
-#include <linux/errno.h>
-#include <linux/smp_lock.h>
-#include <linux/unistd.h>
-#include <linux/version.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
-#include <asm/segment.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/smp_lock.h>
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_mds.h>
-#include <linux/lustre_lite.h>
-#include <linux/lustre_lib.h>
-
-/*
- * Remove page from dirty list
- */
-static void __set_page_clean(struct page *page)
-{
- struct address_space *mapping = page->mapping;
- struct inode *inode;
-
- if (!mapping)
- return;
-
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0))
- spin_lock(&pagecache_lock);
-#endif
-
- list_del(&page->list);
- list_add(&page->list, &mapping->clean_pages);
-
- inode = mapping->host;
- if (list_empty(&mapping->dirty_pages)) {
- CDEBUG(D_INODE, "inode clean\n");
- inode->i_state &= ~I_DIRTY_PAGES;
- }
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0))
- spin_unlock(&pagecache_lock);
-#endif
- EXIT;
-}
-
-inline void set_page_clean(struct page *page)
-{
- if (PageDirty(page)) {
- ClearPageDirty(page);
- __set_page_clean(page);
- }
-}
-
-/* SYNCHRONOUS I/O to object storage for an inode */
-static int ll_brw(int cmd, struct inode *inode, struct page *page, int create)
-{
- struct ll_inode_info *lli = ll_i2info(inode);
- struct lov_stripe_md *lsm = lli->lli_smd;
- struct obd_brw_set *set;
- struct brw_page pg;
- int rc;
- ENTRY;
-
- set = obd_brw_set_new();
- if (set == NULL)
- RETURN(-ENOMEM);
-
- pg.pg = page;
- pg.off = ((obd_off)page->index) << PAGE_SHIFT;
-
- if (cmd == OBD_BRW_WRITE && (pg.off + PAGE_SIZE > inode->i_size))
- pg.count = inode->i_size % PAGE_SIZE;
- else
- pg.count = PAGE_SIZE;
-
- pg.flag = create ? OBD_BRW_CREATE : 0;
-
- set->brw_callback = ll_brw_sync_wait;
- rc = obd_brw(cmd, ll_i2obdconn(inode), lsm, 1, &pg, set);
- if (rc) {
- if (rc != -EIO)
- CERROR("error from obd_brw: rc = %d\n", rc);
- } else {
- rc = ll_brw_sync_wait(set, CB_PHASE_START);
- if (rc)
- CERROR("error from callback: rc = %d\n", rc);
- }
- obd_brw_set_free(set);
-
- RETURN(rc);
-}
-
-/* returns the page unlocked, but with a reference */
-static int ll_readpage(struct file *file, struct page *page)
-{
- struct inode *inode = page->mapping->host;
- obd_off offset = ((obd_off)page->index) << PAGE_SHIFT;
- int rc = 0;
- ENTRY;
-
- if (!PageLocked(page))
- LBUG();
-
- if (inode->i_size <= offset) {
- memset(kmap(page), 0, PAGE_SIZE);
- kunmap(page);
- GOTO(readpage_out, rc);
- }
-
- if (PageUptodate(page)) {
- CERROR("Explain this please?\n");
- GOTO(readpage_out, rc);
- }
-
- rc = ll_brw(OBD_BRW_READ, inode, page, 0);
- EXIT;
-
- readpage_out:
- if (!rc)
- SetPageUptodate(page);
- unlock_page(page);
- return 0;
-} /* ll_readpage */
-
-void ll_truncate(struct inode *inode)
-{
- struct obdo oa = {0};
- struct lov_stripe_md *lsm = ll_i2info(inode)->lli_smd;
- struct lustre_handle *lockhs = NULL;
- int err;
- ENTRY;
-
- if (!lsm) {
- /* object not yet allocated */
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- return;
- }
-
- oa.o_id = lsm->lsm_object_id;
- oa.o_mode = inode->i_mode;
- oa.o_valid = OBD_MD_FLID | OBD_MD_FLMODE | OBD_MD_FLTYPE;
-
- CDEBUG(D_INFO, "calling punch for "LPX64" (all bytes after "LPD64")\n",
- oa.o_id, inode->i_size);
-
- err = ll_size_lock(inode, lsm, inode->i_size, LCK_PW, &lockhs);
- if (err) {
- CERROR("ll_size_lock failed: %d\n", err);
- /* FIXME: What to do here? It's too late to back out... */
- LBUG();
- }
-
- /* truncate == punch from new size to absolute end of file */
- err = obd_punch(ll_i2obdconn(inode), &oa, lsm, inode->i_size,
- OBD_OBJECT_EOF);
- if (err) {
- LBUG();
- CERROR("obd_truncate fails (%d) ino %ld\n", err,
- inode->i_ino);
- } else
- obdo_to_inode(inode, &oa, oa.o_valid);
-
- err = ll_size_unlock(inode, lsm, LCK_PW, lockhs);
- if (err)
- CERROR("ll_size_unlock failed: %d\n", err);
-
- EXIT;
- return;
-} /* ll_truncate */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-
-static int ll_prepare_write(struct file *file, struct page *page, unsigned from,
- unsigned to)
-{
- struct inode *inode = page->mapping->host;
- obd_off offset = ((obd_off)page->index) << PAGE_SHIFT;
- int rc = 0;
- char *addr;
- ENTRY;
-
- addr = kmap(page);
- if (!PageLocked(page))
- LBUG();
-
- if (Page_Uptodate(page))
- GOTO(prepare_done, rc);
-
- /* We're completely overwriting an existing page, so _don't_ set it up
- * to date until commit_write */
- if (from == 0 && to == PAGE_SIZE)
- RETURN(0);
-
- /* We are writing to a new page, no need to read old data */
- if (inode->i_size <= offset) {
- memset(addr, 0, PAGE_SIZE);
- GOTO(prepare_done, rc=0);
- }
-
- rc = ll_brw(OBD_BRW_READ, inode, page, 0);
-
- EXIT;
- prepare_done:
- if (!rc)
- SetPageUptodate(page);
-
- return rc;
-}
-
-/* returns the page unlocked, but with a reference */
-static int ll_writepage(struct page *page)
-{
- struct inode *inode = page->mapping->host;
- int err;
- ENTRY;
-
- if (!PageLocked(page))
- LBUG();
-
- err = ll_brw(OBD_BRW_WRITE, inode, page, 1);
- if ( !err ) {
- //SetPageUptodate(page);
- set_page_clean(page);
- } else {
- CERROR("ll_brw failure %d\n", err);
- }
- unlock_page(page);
- RETURN(err);
-}
-
-
-/* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated
- * too */
-static int ll_commit_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
-{
- struct inode *inode = page->mapping->host;
- struct ll_inode_info *lli = ll_i2info(inode);
- struct lov_stripe_md *md = lli->lli_smd;
- struct brw_page pg;
- struct obd_brw_set *set;
- int rc, create = 1;
- loff_t size;
- ENTRY;
-
- pg.pg = page;
- pg.count = to;
- pg.off = (((obd_off)page->index) << PAGE_SHIFT);
- pg.flag = create ? OBD_BRW_CREATE : 0;
-
- set = obd_brw_set_new();
- if (set == NULL)
- RETURN(-ENOMEM);
-
- SetPageUptodate(page);
-
- if (!PageLocked(page))
- LBUG();
-
- CDEBUG(D_INODE, "commit_page writing (off "LPD64"), count "LPD64"\n",
- pg.off, pg.count);
-
- set->brw_callback = ll_brw_sync_wait;
- rc = obd_brw(OBD_BRW_WRITE, ll_i2obdconn(inode), md, 1, &pg, set);
- if (rc)
- CERROR("error from obd_brw: rc = %d\n", rc);
- else {
- rc = ll_brw_sync_wait(set, CB_PHASE_START);
- if (rc)
- CERROR("error from callback: rc = %d\n", rc);
- }
- obd_brw_set_free(set);
- kunmap(page);
-
- size = pg.off + pg.count;
- /* do NOT truncate when writing in the middle of a file */
- if (size > inode->i_size)
- inode->i_size = size;
-
- RETURN(rc);
-} /* ll_commit_write */
-
-
-static int ll_direct_IO(int rw, struct inode *inode, struct kiobuf *iobuf,
- unsigned long blocknr, int blocksize)
-{
- obd_count bufs_per_obdo = iobuf->nr_pages;
- struct ll_inode_info *lli = ll_i2info(inode);
- struct lov_stripe_md *lsm = lli->lli_smd;
- struct brw_page *pga;
- struct obd_brw_set *set;
- int i, rc = 0;
- ENTRY;
-
- if (!lsm || !lsm->lsm_object_id)
- RETURN(-ENOMEM);
-
- if (blocksize != PAGE_SIZE) {
- CERROR("direct_IO blocksize != PAGE_SIZE\n");
- RETURN(-EINVAL);
- }
-
- set = obd_brw_set_new();
- if (set == NULL)
- RETURN(-ENOMEM);
-
- OBD_ALLOC(pga, sizeof(*pga) * bufs_per_obdo);
- if (!pga) {
- obd_brw_set_free(set);
- RETURN(-ENOMEM);
- }
-
- /* NB: we can't use iobuf->maplist[i]->index for the offset
- * instead of "blocknr" because ->index contains garbage.
- */
- for (i = 0; i < bufs_per_obdo; i++, blocknr++) {
- pga[i].pg = iobuf->maplist[i];
- pga[i].count = PAGE_SIZE;
- pga[i].off = (obd_off)blocknr << PAGE_SHIFT;
- pga[i].flag = OBD_BRW_CREATE;
- }
-
- set->brw_callback = ll_brw_sync_wait;
- rc = obd_brw(rw == WRITE ? OBD_BRW_WRITE : OBD_BRW_READ,
- ll_i2obdconn(inode), lsm, bufs_per_obdo, pga, set);
- if (rc)
- CERROR("error from obd_brw: rc = %d\n", rc);
- else {
- rc = ll_brw_sync_wait(set, CB_PHASE_START);
- if (rc)
- CERROR("error from callback: rc = %d\n", rc);
- }
- obd_brw_set_free(set);
- if (rc == 0)
- rc = bufs_per_obdo * PAGE_SIZE;
-
- OBD_FREE(pga, sizeof(*pga) * bufs_per_obdo);
- RETURN(rc);
-}
-
-int ll_flush_inode_pages(struct inode * inode)
-{
- obd_count bufs_per_obdo = 0;
- obd_size *count = NULL;
- obd_off *offset = NULL;
- obd_flag *flags = NULL;
- int err = 0;
-
- ENTRY;
-
- spin_lock(&pagecache_lock);
-
- spin_unlock(&pagecache_lock);
-
-
- OBD_ALLOC(count, sizeof(*count) * bufs_per_obdo);
- OBD_ALLOC(offset, sizeof(*offset) * bufs_per_obdo);
- OBD_ALLOC(flags, sizeof(*flags) * bufs_per_obdo);
- if (!count || !offset || !flags)
- GOTO(out, err=-ENOMEM);
-
-#if 0
- for (i = 0 ; i < bufs_per_obdo ; i++) {
- count[i] = PAGE_SIZE;
- offset[i] = ((obd_off)(iobuf->maplist[i])->index) << PAGE_SHIFT;
- flags[i] = OBD_BRW_CREATE;
- }
-
- err = obd_brw(OBD_BRW_WRITE, ll_i2obdconn(inode),
- ll_i2info(inode)->lli_smd, bufs_per_obdo,
- iobuf->maplist, count, offset, flags, NULL, NULL);
- if (err == 0)
- err = bufs_per_obdo * 4096;
-#endif
- out:
- OBD_FREE(flags, sizeof(*flags) * bufs_per_obdo);
- OBD_FREE(count, sizeof(*count) * bufs_per_obdo);
- OBD_FREE(offset, sizeof(*offset) * bufs_per_obdo);
- RETURN(err);
-}
-
-#endif
-
-
-struct address_space_operations ll_aops = {
- readpage: ll_readpage,
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0))
- direct_IO: ll_direct_IO,
- writepage: ll_writepage,
- sync_page: block_sync_page,
- prepare_write: ll_prepare_write,
- commit_write: ll_commit_write,
- bmap: NULL
-#endif
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Lustre Light Super operations
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copryright (C) 2002 Cluster File Systems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/module.h>
-#include <linux/random.h>
-#include <linux/version.h>
-#include <linux/lustre_lite.h>
-#include <linux/lustre_ha.h>
-#include <linux/lustre_dlm.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/lprocfs_status.h>
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-kmem_cache_t *ll_file_data_slab;
-extern struct address_space_operations ll_aops;
-extern struct address_space_operations ll_dir_aops;
-struct super_operations ll_super_operations;
-
-extern int ll_recover(struct recovd_data *, int);
-extern int ll_commitcbd_setup(struct ll_sb_info *);
-extern int ll_commitcbd_cleanup(struct ll_sb_info *);
-
-extern void ll_proc_namespace(struct super_block* sb, char* osc, char* mdc);
-
-static char *ll_read_opt(const char *opt, char *data)
-{
- char *value;
- char *retval;
- ENTRY;
-
- CDEBUG(D_SUPER, "option: %s, data %s\n", opt, data);
- if ( strncmp(opt, data, strlen(opt)) )
- RETURN(NULL);
- if ( (value = strchr(data, '=')) == NULL )
- RETURN(NULL);
-
- value++;
- OBD_ALLOC(retval, strlen(value) + 1);
- if ( !retval ) {
- CERROR("out of memory!\n");
- RETURN(NULL);
- }
-
- memcpy(retval, value, strlen(value)+1);
- CDEBUG(D_SUPER, "Assigned option: %s, value %s\n", opt, retval);
- RETURN(retval);
-}
-
-static int ll_set_opt(const char *opt, char *data, int fl)
-{
- ENTRY;
-
- CDEBUG(D_SUPER, "option: %s, data %s\n", opt, data);
- if ( strncmp(opt, data, strlen(opt)) )
- RETURN(0);
- else
- RETURN(fl);
-}
-
-static void ll_options(char *options, char **ost, char **mds, int *flags)
-{
- char *this_char;
- ENTRY;
-
- if (!options) {
- EXIT;
- return;
- }
-
- for (this_char = strtok (options, ",");
- this_char != NULL;
- this_char = strtok (NULL, ",")) {
- CDEBUG(D_SUPER, "this_char %s\n", this_char);
- if ( (!*ost && (*ost = ll_read_opt("osc", this_char)))||
- (!*mds && (*mds = ll_read_opt("mdc", this_char)))||
- (!(*flags & LL_SBI_NOLCK) && ((*flags) = (*flags) |
- ll_set_opt("nolock", this_char, LL_SBI_NOLCK))) )
- continue;
- }
- EXIT;
-}
-
-#ifndef log2
-#define log2(n) ffz(~(n))
-#endif
-
-static struct super_block * ll_read_super(struct super_block *sb,
- void *data, int silent)
-{
- struct inode *root = 0;
- struct obd_device *obd;
- struct ll_sb_info *sbi;
- char *osc = NULL;
- char *mdc = NULL;
- int err;
- struct ll_fid rootfid;
- struct obd_statfs osfs;
- struct ptlrpc_request *request = NULL;
- struct ptlrpc_connection *mdc_conn;
- struct ll_read_inode2_cookie lic;
- class_uuid_t uuid;
-
- ENTRY;
- MOD_INC_USE_COUNT;
-
- OBD_ALLOC(sbi, sizeof(*sbi));
- if (!sbi) {
- MOD_DEC_USE_COUNT;
- RETURN(NULL);
- }
-
- INIT_LIST_HEAD(&sbi->ll_conn_chain);
- INIT_LIST_HEAD(&sbi->ll_orphan_dentry_list);
- generate_random_uuid(uuid);
- class_uuid_unparse(uuid, sbi->ll_sb_uuid);
-
- sb->u.generic_sbp = sbi;
-
- ll_options(data, &osc, &mdc, &sbi->ll_flags);
-
- if (!osc) {
- CERROR("no osc\n");
- GOTO(out_free, sb = NULL);
- }
-
- if (!mdc) {
- CERROR("no mdc\n");
- GOTO(out_free, sb = NULL);
- }
-
- obd = class_uuid2obd(mdc);
- if (!obd) {
- CERROR("MDC %s: not setup or attached\n", mdc);
- GOTO(out_free, sb = NULL);
- }
-
- err = obd_connect(&sbi->ll_mdc_conn, obd, sbi->ll_sb_uuid,
- ptlrpc_recovd, ll_recover);
- if (err) {
- CERROR("cannot connect to %s: rc = %d\n", mdc, err);
- GOTO(out_free, sb = NULL);
- }
-
- mdc_conn = sbi2mdc(sbi)->cl_import.imp_connection;
- list_add(&mdc_conn->c_sb_chain, &sbi->ll_conn_chain);
-
- obd = class_uuid2obd(osc);
- if (!obd) {
- CERROR("OSC %s: not setup or attached\n", osc);
- GOTO(out_mdc, sb = NULL);
- }
-
- err = obd_connect(&sbi->ll_osc_conn, obd, sbi->ll_sb_uuid,
- ptlrpc_recovd, ll_recover);
- if (err) {
- CERROR("cannot connect to %s: rc = %d\n", osc, err);
- GOTO(out_mdc, sb = NULL);
- }
-
- err = mdc_getstatus(&sbi->ll_mdc_conn, &rootfid);
- if (err) {
- CERROR("cannot mds_connect: rc = %d\n", err);
- GOTO(out_mdc, sb = NULL);
- }
- CDEBUG(D_SUPER, "rootfid "LPU64"\n", rootfid.id);
- sbi->ll_rootino = rootfid.id;
-
- memset(&osfs, 0, sizeof(osfs));
- err = obd_statfs(&sbi->ll_mdc_conn, &osfs);
- sb->s_blocksize = osfs.os_bsize;
- sb->s_blocksize_bits = log2(osfs.os_bsize);
- sb->s_magic = LL_SUPER_MAGIC;
- sb->s_maxbytes = (1ULL << (32 + 9)) - osfs.os_bsize;
-
- sb->s_op = &ll_super_operations;
-
- /* make root inode */
- err = mdc_getattr(&sbi->ll_mdc_conn, sbi->ll_rootino, S_IFDIR,
- OBD_MD_FLNOTOBD|OBD_MD_FLBLOCKS, 0, &request);
- if (err) {
- CERROR("mdc_getattr failed for root: rc = %d\n", err);
- GOTO(out_request, sb = NULL);
- }
-
- /* initialize committed transaction callback daemon */
- spin_lock_init(&sbi->ll_commitcbd_lock);
- init_waitqueue_head(&sbi->ll_commitcbd_waitq);
- init_waitqueue_head(&sbi->ll_commitcbd_ctl_waitq);
- sbi->ll_commitcbd_flags = 0;
- err = ll_commitcbd_setup(sbi);
- if (err) {
- CERROR("failed to start commit callback daemon: rc = %d\n",err);
- GOTO(out_request, sb = NULL);
- }
-
- lic.lic_body = lustre_msg_buf(request->rq_repmsg, 0);
- lic.lic_lmm = NULL;
- LASSERT(sbi->ll_rootino != 0);
- root = iget4(sb, sbi->ll_rootino, NULL, &lic);
-
- if (root) {
- sb->s_root = d_alloc_root(root);
- } else {
- CERROR("lustre_lite: bad iget4 for root\n");
- GOTO(out_cdb, sb = NULL);
- }
-
- ptlrpc_req_finished(request);
- request = NULL;
- ll_proc_namespace(sb, osc, mdc);
-
-out_dev:
- if (mdc)
- OBD_FREE(mdc, strlen(mdc) + 1);
- if (osc)
- OBD_FREE(osc, strlen(osc) + 1);
-
- RETURN(sb);
-
-out_cdb:
- ll_commitcbd_cleanup(sbi);
-out_request:
- ptlrpc_req_finished(request);
- obd_disconnect(&sbi->ll_osc_conn);
-out_mdc:
- obd_disconnect(&sbi->ll_mdc_conn);
-out_free:
- OBD_FREE(sbi, sizeof(*sbi));
-
- MOD_DEC_USE_COUNT;
- goto out_dev;
-} /* ll_read_super */
-
-static void ll_put_super(struct super_block *sb)
-{
- struct ll_sb_info *sbi = ll_s2sbi(sb);
- struct list_head *tmp, *next;
- struct ll_fid rootfid;
- ENTRY;
-
- list_del(&sbi->ll_conn_chain);
- ll_commitcbd_cleanup(sbi);
- obd_disconnect(&sbi->ll_osc_conn);
-
- /* NULL request to force sync on the MDS, and get the last_committed
- * value to flush remaining RPCs from the sending queue on client.
- *
- * XXX This should be an mdc_sync() call to sync the whole MDS fs,
- * which we can call for other reasons as well.
- */
- mdc_getstatus(&sbi->ll_mdc_conn, &rootfid);
-
- lprocfs_dereg_mnt(sbi->ll_proc_root);
- sbi->ll_proc_root = NULL;
-
- obd_disconnect(&sbi->ll_mdc_conn);
-
- spin_lock(&dcache_lock);
- list_for_each_safe(tmp, next, &sbi->ll_orphan_dentry_list) {
- struct dentry *dentry = list_entry(tmp, struct dentry, d_hash);
- shrink_dcache_parent(dentry);
- }
- spin_unlock(&dcache_lock);
-
- OBD_FREE(sbi, sizeof(*sbi));
-
- MOD_DEC_USE_COUNT;
- EXIT;
-} /* ll_put_super */
-
-static void ll_clear_inode(struct inode *inode)
-{
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ll_inode_info *lli = ll_i2info(inode);
- int rc;
- ENTRY;
-
- rc = mdc_cancel_unused(&sbi->ll_mdc_conn, inode, LDLM_FL_NO_CALLBACK);
- if (rc < 0) {
- CERROR("mdc_cancel_unused: %d\n", rc);
- /* XXX FIXME do something dramatic */
- }
-
- if (lli->lli_smd) {
- rc = obd_cancel_unused(&sbi->ll_osc_conn, lli->lli_smd, 0);
- if (rc < 0) {
- CERROR("obd_cancel_unused: %d\n", rc);
- /* XXX FIXME do something dramatic */
- }
- }
-
- if (atomic_read(&inode->i_count) == 0) {
- char *symlink_name = lli->lli_symlink_name;
-
- if (lli->lli_smd)
- obd_free_memmd(&sbi->ll_osc_conn, &lli->lli_smd);
-
- if (symlink_name) {
- OBD_FREE(symlink_name, strlen(symlink_name) + 1);
- lli->lli_symlink_name = NULL;
- }
- }
-
- EXIT;
-}
-
-static void ll_delete_inode(struct inode *inode)
-{
- ENTRY;
- if (S_ISREG(inode->i_mode)) {
- int err;
- struct obdo *oa;
- struct lov_stripe_md *lsm = ll_i2info(inode)->lli_smd;
-
- if (!lsm)
- GOTO(out, -EINVAL);
-
- if (lsm->lsm_object_id == 0) {
- CERROR("This really happens\n");
- /* No obdo was ever created */
- GOTO(out, 0);
- }
-
- oa = obdo_alloc();
- if (oa == NULL)
- GOTO(out, -ENOMEM);
-
- oa->o_id = lsm->lsm_object_id;
- oa->o_mode = inode->i_mode;
- oa->o_valid = OBD_MD_FLID | OBD_MD_FLEASIZE | OBD_MD_FLTYPE;
-
- err = obd_destroy(ll_i2obdconn(inode), oa, lsm);
- obdo_free(oa);
- CDEBUG(D_SUPER, "obd destroy of objid "LPX64" error %d\n",
- lsm->lsm_object_id, err);
- }
-out:
- clear_inode(inode);
- EXIT;
-}
-
-/* like inode_setattr, but doesn't mark the inode dirty */
-static int ll_attr2inode(struct inode * inode, struct iattr * attr, int trunc)
-{
- unsigned int ia_valid = attr->ia_valid;
- int error = 0;
-
- if ((ia_valid & ATTR_SIZE) && trunc) {
- error = vmtruncate(inode, attr->ia_size);
- if (error)
- goto out;
- } else if (ia_valid & ATTR_SIZE)
- inode->i_size = attr->ia_size;
-
- if (ia_valid & ATTR_UID)
- inode->i_uid = attr->ia_uid;
- if (ia_valid & ATTR_GID)
- inode->i_gid = attr->ia_gid;
- if (ia_valid & ATTR_ATIME)
- inode->i_atime = attr->ia_atime;
- if (ia_valid & ATTR_MTIME)
- inode->i_mtime = attr->ia_mtime;
- if (ia_valid & ATTR_CTIME)
- inode->i_ctime = attr->ia_ctime;
- if (ia_valid & ATTR_MODE) {
- inode->i_mode = attr->ia_mode;
- if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
- inode->i_mode &= ~S_ISGID;
- }
-out:
- return error;
-}
-
-int ll_inode_setattr(struct inode *inode, struct iattr *attr, int do_trunc)
-{
- struct ptlrpc_request *request = NULL;
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- int err;
-
- ENTRY;
-
- /* change incore inode */
- ll_attr2inode(inode, attr, do_trunc);
-
- err = mdc_setattr(&sbi->ll_mdc_conn, inode, attr, &request);
- if (err)
- CERROR("mdc_setattr fails (%d)\n", err);
-
- ptlrpc_req_finished(request);
-
- RETURN(err);
-}
-
-int ll_setattr(struct dentry *de, struct iattr *attr)
-{
- int rc = inode_change_ok(de->d_inode, attr);
-
- if (rc)
- return rc;
-
- return ll_inode_setattr(de->d_inode, attr, 1);
-}
-
-static int ll_statfs(struct super_block *sb, struct statfs *sfs)
-{
- struct ll_sb_info *sbi = ll_s2sbi(sb);
- struct obd_statfs osfs;
- int rc;
- ENTRY;
-
- memset(sfs, 0, sizeof(*sfs));
- rc = obd_statfs(&sbi->ll_mdc_conn, &osfs);
- statfs_unpack(sfs, &osfs);
- if (rc)
- CERROR("mdc_statfs fails: rc = %d\n", rc);
- else
- CDEBUG(D_SUPER, "mdc_statfs shows blocks "LPU64"/"LPU64
- " objects "LPU64"/"LPU64"\n",
- osfs.os_bavail, osfs.os_blocks,
- osfs.os_ffree, osfs.os_files);
-
- /* temporary until mds_statfs returns statfs info for all OSTs */
- if (!rc) {
- rc = obd_statfs(&sbi->ll_osc_conn, &osfs);
- if (rc) {
- CERROR("obd_statfs fails: rc = %d\n", rc);
- GOTO(out, rc);
- }
- CDEBUG(D_SUPER, "obd_statfs shows blocks "LPU64"/"LPU64
- " objects "LPU64"/"LPU64"\n",
- osfs.os_bavail, osfs.os_blocks,
- osfs.os_ffree, osfs.os_files);
-
- while (osfs.os_blocks > ~0UL) {
- sfs->f_bsize <<= 1;
-
- osfs.os_blocks >>= 1;
- osfs.os_bfree >>= 1;
- osfs.os_bavail >>= 1;
- }
- sfs->f_blocks = osfs.os_blocks;
- sfs->f_bfree = osfs.os_bfree;
- sfs->f_bavail = osfs.os_bavail;
- if (osfs.os_ffree < (__u64)sfs->f_ffree)
- sfs->f_ffree = osfs.os_ffree;
- }
-
-out:
- RETURN(rc);
-}
-
-void ll_update_inode(struct inode *inode, struct mds_body *body)
-{
- if (body->valid & OBD_MD_FLID)
- inode->i_ino = body->ino;
- if (body->valid & OBD_MD_FLATIME)
- inode->i_atime = body->atime;
- if (body->valid & OBD_MD_FLMTIME)
- inode->i_mtime = body->mtime;
- if (body->valid & OBD_MD_FLCTIME)
- inode->i_ctime = body->ctime;
- if (body->valid & OBD_MD_FLMODE)
- inode->i_mode = (inode->i_mode & S_IFMT)|(body->mode & ~S_IFMT);
- if (body->valid & OBD_MD_FLTYPE)
- inode->i_mode = (inode->i_mode & ~S_IFMT)|(body->mode & S_IFMT);
- if (body->valid & OBD_MD_FLUID)
- inode->i_uid = body->uid;
- if (body->valid & OBD_MD_FLGID)
- inode->i_gid = body->gid;
- if (body->valid & OBD_MD_FLFLAGS)
- inode->i_flags = body->flags;
- if (body->valid & OBD_MD_FLNLINK)
- inode->i_nlink = body->nlink;
- if (body->valid & OBD_MD_FLGENER)
- inode->i_generation = body->generation;
- if (body->valid & OBD_MD_FLRDEV)
- inode->i_rdev = body->rdev;
- if (body->valid & OBD_MD_FLSIZE)
- inode->i_size = body->size;
-}
-
-static void ll_read_inode2(struct inode *inode, void *opaque)
-{
- struct ll_read_inode2_cookie *lic = opaque;
- struct mds_body *body = lic->lic_body;
- struct ll_inode_info *lli = ll_i2info(inode);
- ENTRY;
-
- sema_init(&lli->lli_open_sem, 1);
- atomic_set(&lli->lli_open_count, 0);
-
- /* core attributes first */
- ll_update_inode(inode, body);
-
- //if (body->valid & OBD_MD_FLEASIZE)
- LASSERT(!lli->lli_smd);
- if (lic && lic->lic_lmm)
- obd_unpackmd(ll_i2obdconn(inode), &lli->lli_smd, lic->lic_lmm);
-
- /* Get the authoritative file size */
- if (lli->lli_smd && (inode->i_mode & S_IFREG)) {
- int rc;
- LASSERT(lli->lli_smd->lsm_object_id != 0);
- rc = ll_file_size(inode, lli->lli_smd);
- if (rc) {
- CERROR("ll_file_size: %d\n", rc);
- /* FIXME: need to somehow prevent inode creation */
- LBUG();
- make_bad_inode(inode);
- }
- }
-
- /* OIDEBUG(inode); */
-
- if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ll_file_inode_operations;
- inode->i_fop = &ll_file_operations;
- inode->i_mapping->a_ops = &ll_aops;
- EXIT;
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &ll_dir_inode_operations;
- inode->i_fop = &ll_dir_operations;
- inode->i_mapping->a_ops = &ll_dir_aops;
- EXIT;
- } else if (S_ISLNK(inode->i_mode)) {
- inode->i_op = &ll_fast_symlink_inode_operations;
- EXIT;
- } else {
- init_special_inode(inode, inode->i_mode, inode->i_rdev);
- EXIT;
- }
-}
-
-static inline void invalidate_request_list(struct list_head *req_list)
-{
- struct list_head *tmp, *n;
- list_for_each_safe(tmp, n, req_list) {
- struct ptlrpc_request *req =
- list_entry(tmp, struct ptlrpc_request, rq_list);
- CERROR("invalidating req xid "LPD64" op %d to %s:%d\n",
- (unsigned long long)req->rq_xid, req->rq_reqmsg->opc,
- req->rq_connection->c_remote_uuid,
- req->rq_import->imp_client->cli_request_portal);
- req->rq_flags |= PTL_RPC_FL_ERR;
- wake_up(&req->rq_wait_for_rep);
- }
-}
-
-void ll_umount_begin(struct super_block *sb)
-{
- struct ll_sb_info *sbi = ll_s2sbi(sb);
- struct list_head *ctmp;
-
- ENTRY;
-
- list_for_each(ctmp, &sbi->ll_conn_chain) {
- struct ptlrpc_connection *conn;
- conn = list_entry(ctmp, struct ptlrpc_connection, c_sb_chain);
-
- spin_lock(&conn->c_lock);
- /* XXX should just be dealing with imports, probably through
- * XXX iocontrol, need next-gen recovery! */
- conn->c_flags |= CONN_INVALID;
- /* invalidate_request_list(&conn->c_sending_head); */
- invalidate_request_list(&conn->c_delayed_head);
- spin_unlock(&conn->c_lock);
- }
-
- EXIT;
-}
-
-/* exported operations */
-struct super_operations ll_super_operations =
-{
- read_inode2: ll_read_inode2,
- clear_inode: ll_clear_inode,
- delete_inode: ll_delete_inode,
- put_super: ll_put_super,
- statfs: ll_statfs,
- umount_begin: ll_umount_begin
-};
-
-struct file_system_type lustre_lite_fs_type = {
- "lustre_lite", 0, ll_read_super, NULL
-};
-
-static int __init init_lustre_lite(void)
-{
- printk(KERN_INFO "Lustre Lite 0.5.14, info@clusterfs.com\n");
- ll_file_data_slab = kmem_cache_create("ll_file_data",
- sizeof(struct ll_file_data), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (ll_file_data_slab == NULL)
- return -ENOMEM;
- return register_filesystem(&lustre_lite_fs_type);
-}
-
-static void __exit exit_lustre_lite(void)
-{
- unregister_filesystem(&lustre_lite_fs_type);
- kmem_cache_destroy(ll_file_data_slab);
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Lite Client File System v1.0");
-MODULE_LICENSE("GPL");
-
-module_init(init_lustre_lite);
-module_exit(exit_lustre_lite);
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Lustre Light Super operations
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copryright (C) 2002 Cluster File Systems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/module.h>
-#include <linux/random.h>
-#include <linux/version.h>
-#include <linux/lustre_lite.h>
-#include <linux/lustre_ha.h>
-#include <linux/lustre_dlm.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/lprocfs_status.h>
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
-kmem_cache_t *ll_file_data_slab;
-extern struct address_space_operations ll_aops;
-extern struct address_space_operations ll_dir_aops;
-struct super_operations ll_super_operations;
-
-extern int ll_init_inodecache(void);
-extern void ll_destroy_inodecache(void);
-extern int ll_recover(struct recovd_data *, int);
-extern int ll_commitcbd_setup(struct ll_sb_info *);
-extern int ll_commitcbd_cleanup(struct ll_sb_info *);
-int ll_read_inode2(struct inode *inode, void *opaque);
-
-extern void ll_proc_namespace(struct super_block* sb, char* osc, char* mdc)
-
-static char *ll_read_opt(const char *opt, char *data)
-{
- char *value;
- char *retval;
- ENTRY;
-
- CDEBUG(D_SUPER, "option: %s, data %s\n", opt, data);
- if ( strncmp(opt, data, strlen(opt)) )
- RETURN(NULL);
- if ( (value = strchr(data, '=')) == NULL )
- RETURN(NULL);
-
- value++;
- OBD_ALLOC(retval, strlen(value) + 1);
- if ( !retval ) {
- CERROR("out of memory!\n");
- RETURN(NULL);
- }
-
- memcpy(retval, value, strlen(value)+1);
- CDEBUG(D_SUPER, "Assigned option: %s, value %s\n", opt, retval);
- RETURN(retval);
-}
-
-static int ll_set_opt(const char *opt, char *data, int fl)
-{
- ENTRY;
-
- CDEBUG(D_SUPER, "option: %s, data %s\n", opt, data);
- if ( strncmp(opt, data, strlen(opt)) )
- RETURN(0);
- else
- RETURN(fl);
-}
-
-static void ll_options(char *options, char **ost, char **mds, int *flags)
-{
- char *opt_ptr = options;
- char *this_char;
- ENTRY;
-
- if (!options) {
- EXIT;
- return;
- }
-
- while ((this_char = strsep (&opt_ptr, ",")) != NULL) {
- CDEBUG(D_SUPER, "this_char %s\n", this_char);
- if ( (!*ost && (*ost = ll_read_opt("osc", this_char)))||
- (!*mds && (*mds = ll_read_opt("mdc", this_char)))||
- (!(*flags & LL_SBI_NOLCK) && ((*flags) = (*flags) |
- ll_set_opt("nolock", this_char, LL_SBI_NOLCK))) )
- continue;
- }
- EXIT;
-}
-
-#ifndef log2
-#define log2(n) ffz(~(n))
-#endif
-
-
-static int ll_fill_super(struct super_block *sb, void *data, int silent)
-{
- struct inode *root = 0;
- struct obd_device *obd;
- struct ll_sb_info *sbi;
- char *osc = NULL;
- char *mdc = NULL;
- int err;
- struct ll_fid rootfid;
- struct obd_statfs osfs;
- struct ptlrpc_request *request = NULL;
- struct ptlrpc_connection *mdc_conn;
- struct ll_read_inode2_cookie lic;
- class_uuid_t uuid;
-
- ENTRY;
- MOD_INC_USE_COUNT;
-
- OBD_ALLOC(sbi, sizeof(*sbi));
- if (!sbi) {
- MOD_DEC_USE_COUNT;
- RETURN(-ENOMEM);
- }
-
- INIT_LIST_HEAD(&sbi->ll_conn_chain);
- generate_random_uuid(uuid);
- class_uuid_unparse(uuid, sbi->ll_sb_uuid);
-
- sb->s_fs_info = sbi;
-
- ll_options(data, &osc, &mdc, &sbi->ll_flags);
-
- if (!osc) {
- CERROR("no osc\n");
- GOTO(out_free, sb = NULL);
- }
-
- if (!mdc) {
- CERROR("no mdc\n");
- GOTO(out_free, sb = NULL);
- }
-
- obd = class_uuid2obd(mdc);
- if (!obd) {
- CERROR("MDC %s: not setup or attached\n", mdc);
- GOTO(out_free, sb = NULL);
- }
-
- err = obd_connect(&sbi->ll_mdc_conn, obd, sbi->ll_sb_uuid,
- ptlrpc_recovd, ll_recover);
- if (err) {
- CERROR("cannot connect to %s: rc = %d\n", mdc, err);
- GOTO(out_free, sb = NULL);
- }
-
- mdc_conn = sbi2mdc(sbi)->cl_import.imp_connection;
- list_add(&mdc_conn->c_sb_chain, &sbi->ll_conn_chain);
-
- obd = class_uuid2obd(osc);
- if (!obd) {
- CERROR("OSC %s: not setup or attached\n", osc);
- GOTO(out_mdc, sb = NULL);
- }
-
- err = obd_connect(&sbi->ll_osc_conn, obd, sbi->ll_sb_uuid,
- ptlrpc_recovd, ll_recover);
- if (err) {
- CERROR("cannot connect to %s: rc = %d\n", osc, err);
- GOTO(out_mdc, sb = NULL);
- }
-
- err = mdc_getstatus(&sbi->ll_mdc_conn, &rootfid);
- if (err) {
- CERROR("cannot mds_connect: rc = %d\n", err);
- GOTO(out_mdc, sb = NULL);
- }
- CDEBUG(D_SUPER, "rootfid "LPU64"\n", rootfid.id);
- sbi->ll_rootino = rootfid.id;
-
- memset(&osfs, 0, sizeof(osfs));
- err = mdc_statfs(&sbi->ll_mdc_conn, &osfs);
- sb->s_blocksize = osfs.os_bsize;
- sb->s_blocksize_bits = log2(osfs.os_bsize);
- sb->s_magic = LL_SUPER_MAGIC;
- sb->s_maxbytes = (1ULL << (32 + 9)) - osfs.os_bsize;
-
- sb->s_op = &ll_super_operations;
-
- /* make root inode */
- err = mdc_getattr(&sbi->ll_mdc_conn, sbi->ll_rootino, S_IFDIR,
- OBD_MD_FLNOTOBD|OBD_MD_FLBLOCKS, 0, &request);
- if (err) {
- CERROR("mdc_getattr failed for root: rc = %d\n", err);
- GOTO(out_request, sb = NULL);
- }
-
- /* initialize committed transaction callback daemon */
- spin_lock_init(&sbi->ll_commitcbd_lock);
- init_waitqueue_head(&sbi->ll_commitcbd_waitq);
- init_waitqueue_head(&sbi->ll_commitcbd_ctl_waitq);
- sbi->ll_commitcbd_flags = 0;
- err = ll_commitcbd_setup(sbi);
- if (err) {
- CERROR("failed to start commit callback daemon: rc = %d\n",err);
- GOTO(out_request, sb = NULL);
- }
-
- lic.lic_body = lustre_msg_buf(request->rq_repmsg, 0);
- lic.lic_lmm = NULL;
- root = iget5_locked(sb, sbi->ll_rootino, NULL,
- ll_read_inode2, &lic);
-
- if (root) {
- sb->s_root = d_alloc_root(root);
- } else {
- CERROR("lustre_lite: bad iget4 for root\n");
- GOTO(out_cdb, sb = NULL);
- }
-
- ptlrpc_req_finished(request);
- request = NULL;
- ll_proc_namespace(sb, osc, mdc)
-out_dev:
- if (mdc)
- OBD_FREE(mdc, strlen(mdc) + 1);
- if (osc)
- OBD_FREE(osc, strlen(osc) + 1);
-
- RETURN(0);
-
-out_cdb:
- ll_commitcbd_cleanup(sbi);
-out_request:
- ptlrpc_req_finished(request);
- obd_disconnect(&sbi->ll_osc_conn);
-out_mdc:
- obd_disconnect(&sbi->ll_mdc_conn);
-out_free:
- OBD_FREE(sbi, sizeof(*sbi));
-
- MOD_DEC_USE_COUNT;
- goto out_dev;
-} /* ll_fill_super */
-
-struct super_block * ll_get_sb(struct file_system_type *fs_type,
- int flags, char *devname, void * data)
-{
- return get_sb_nodev(fs_type, flags, data, ll_fill_super);
-}
-
-static void ll_put_super(struct super_block *sb)
-{
- struct ll_sb_info *sbi = ll_s2sbi(sb);
- struct ll_fid rootfid;
- ENTRY;
-
- list_del(&sbi->ll_conn_chain);
- ll_commitcbd_cleanup(sbi);
- obd_disconnect(&sbi->ll_osc_conn);
-
- /* NULL request to force sync on the MDS, and get the last_committed
- * value to flush remaining RPCs from the pending queue on client.
- *
- * XXX This should be an mdc_sync() call to sync the whole MDS fs,
- * which we can call for other reasons as well.
- */
- mdc_getstatus(&sbi->ll_mdc_conn, &rootfid);
-
- lprocfs_dereg_mnt(sbi->ll_proc_root);
- sbi->ll_proc_root = NULL;
-
- obd_disconnect(&sbi->ll_mdc_conn);
- OBD_FREE(sbi, sizeof(*sbi));
-
- MOD_DEC_USE_COUNT;
- EXIT;
-} /* ll_put_super */
-
-static void ll_clear_inode(struct inode *inode)
-{
- ENTRY;
-
- if (atomic_read(&inode->i_count) == 0) {
- struct ll_inode_info *lli = ll_i2info(inode);
- char *symlink_name = lli->lli_symlink_name;
-
- if (lli->lli_smd)
- obd_free_memmd(&sbi->ll_osc_conn, &lli->lli_smd);
- if (symlink_name) {
- OBD_FREE(symlink_name, strlen(symlink_name) + 1);
- lli->lli_symlink_name = NULL;
- }
- }
- EXIT;
-}
-
-static void ll_delete_inode(struct inode *inode)
-{
- ENTRY;
- if (S_ISREG(inode->i_mode)) {
- int err;
- struct obdo *oa;
- struct lov_stripe_md *lsm = ll_i2info(inode)->lli_smd;
-
- if (!lsm)
- GOTO(out, -EINVAL);
-
- if (lsm->lsm_object_id == 0) {
- CERROR("This really happens\n");
- /* No obdo was ever created */
- GOTO(out, 0);
- }
-
- oa = obdo_alloc();
- if (oa == NULL)
- GOTO(out, -ENOMEM);
-
- oa->o_id = lsm->lsm_object_id;
- oa->o_mode = inode->i_mode;
- oa->o_valid = OBD_MD_FLID | OBD_MD_FLEASIZE | OBD_MD_FLTYPE;
-
- err = obd_destroy(ll_i2obdconn(inode), oa, lsm);
- obdo_free(oa);
- CDEBUG(D_SUPER, "obd destroy of objid "LPX64" error %d\n",
- lsm->lsm_object_id, err);
- }
-out:
- clear_inode(inode);
- EXIT;
-}
-
-/* like inode_setattr, but doesn't mark the inode dirty */
-static int ll_attr2inode(struct inode * inode, struct iattr * attr, int trunc)
-{
- unsigned int ia_valid = attr->ia_valid;
- int error = 0;
-
- if ((ia_valid & ATTR_SIZE) && trunc) {
- error = vmtruncate(inode, attr->ia_size);
- if (error)
- goto out;
- } else if (ia_valid & ATTR_SIZE)
- inode->i_size = attr->ia_size;
-
- if (ia_valid & ATTR_UID)
- inode->i_uid = attr->ia_uid;
- if (ia_valid & ATTR_GID)
- inode->i_gid = attr->ia_gid;
- if (ia_valid & ATTR_ATIME)
- inode->i_atime = attr->ia_atime;
- if (ia_valid & ATTR_MTIME)
- inode->i_mtime = attr->ia_mtime;
- if (ia_valid & ATTR_CTIME)
- inode->i_ctime = attr->ia_ctime;
- if (ia_valid & ATTR_MODE) {
- inode->i_mode = attr->ia_mode;
- if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
- inode->i_mode &= ~S_ISGID;
- }
-out:
- return error;
-}
-
-int ll_inode_setattr(struct inode *inode, struct iattr *attr, int do_trunc)
-{
- struct ptlrpc_request *request = NULL;
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- int err;
-
- ENTRY;
-
- /* change incore inode */
- ll_attr2inode(inode, attr, do_trunc);
-
- err = mdc_setattr(&sbi->ll_mdc_conn, inode, attr, &request);
- if (err)
- CERROR("mdc_setattr fails (%d)\n", err);
-
- ptlrpc_req_finished(request);
-
- RETURN(err);
-}
-
-int ll_setattr(struct dentry *de, struct iattr *attr)
-{
- int rc = inode_change_ok(de->d_inode, attr);
-
- if (rc)
- return rc;
-
- return ll_inode_setattr(de->d_inode, attr, 1);
-}
-
-static int ll_statfs(struct super_block *sb, struct statfs *sfs)
-{
- struct ll_sb_info *sbi = ll_s2sbi(sb);
- struct obd_statfs osfs;
- int rc;
- ENTRY;
-
- memset(sfs, 0, sizeof(*sfs));
- rc = obd_statfs(&sbi->ll_mdc_conn, &osfs);
- statfs_unpack(sfs, &osfs);
- if (rc)
- CERROR("mdc_statfs fails: rc = %d\n", rc);
- else
- CDEBUG(D_SUPER, "mdc_statfs shows blocks "LPU64"/"LPU64
- " objects "LPU64"/"LPU64"\n",
- osfs.os_bavail, osfs.os_blocks,
- osfs.os_ffree, osfs.os_files);
-
- /* temporary until mds_statfs returns statfs info for all OSTs */
- if (!rc) {
- rc = obd_statfs(&sbi->ll_osc_conn, &osfs);
- if (rc) {
- CERROR("obd_statfs fails: rc = %d\n", rc);
- GOTO(out, rc);
- }
- CDEBUG(D_SUPER, "obd_statfs shows blocks "LPU64"/"LPU64
- " objects "LPU64"/"LPU64"\n",
- osfs.os_bavail, osfs.os_blocks,
- osfs.os_ffree, osfs.os_files);
-
- while (osfs.os_blocks > ~0UL) {
- sfs->f_bsize <<= 1;
-
- osfs.os_blocks >>= 1;
- osfs.os_bfree >>= 1;
- osfs.os_bavail >>= 1;
- }
- sfs->f_blocks = osfs.os_blocks;
- sfs->f_bfree = osfs.os_bfree;
- sfs->f_bavail = osfs.os_bavail;
- if (osfs.os_ffree < (__u64)sfs->f_ffree)
- sfs->f_ffree = osfs.os_ffree;
- }
-
-out:
- RETURN(rc);
-}
-
-void ll_update_inode(struct inode *inode, struct mds_body *body)
-{
- if (body->valid & OBD_MD_FLID)
- inode->i_ino = body->ino;
- if (body->valid & OBD_MD_FLATIME)
- inode->i_atime = body->atime;
- if (body->valid & OBD_MD_FLMTIME)
- inode->i_mtime = body->mtime;
- if (body->valid & OBD_MD_FLCTIME)
- inode->i_ctime = body->ctime;
- if (body->valid & OBD_MD_FLMODE)
- inode->i_mode = (inode->i_mode & S_IFMT)|(body->mode & ~S_IFMT);
- if (body->valid & OBD_MD_FLTYPE)
- inode->i_mode = (inode->i_mode & ~S_IFMT)|(body->mode & S_IFMT);
- if (body->valid & OBD_MD_FLUID)
- inode->i_uid = body->uid;
- if (body->valid & OBD_MD_FLGID)
- inode->i_gid = body->gid;
- if (body->valid & OBD_MD_FLFLAGS)
- inode->i_flags = body->flags;
- if (body->valid & OBD_MD_FLNLINK)
- inode->i_nlink = body->nlink;
- if (body->valid & OBD_MD_FLGENER)
- inode->i_generation = body->generation;
- if (body->valid & OBD_MD_FLRDEV)
- inode->i_rdev = to_kdev_t(body->rdev);
- if (body->valid & OBD_MD_FLSIZE)
- inode->i_size = body->size;
-}
-
-int ll_read_inode2(struct inode *inode, void *opaque)
-{
- struct ll_read_inode2_cookie *lic = opaque;
- struct mds_body *body = lic->lic_body;
- struct ll_inode_info *lli = ll_i2info(inode);
- int rc = 0;
- ENTRY;
-
- sema_init(&lli->lli_open_sem, 1);
-
- /* core attributes first */
- ll_update_inode(inode, body);
-
- //if (body->valid & OBD_MD_FLEASIZE)
- LASSERT(!lli->lli_smd);
- if (lic && lic->lic_lmm)
- obd_unpackmd(ll_i2obdconn(inode), &lli->lli_smd, lic->lic_lmm);
-
- /* Get the authoritative file size */
- if (lli->lli_smd && S_ISREG(inode->i_mode)) {
- rc = ll_file_size(inode, lli->lli_smd);
- if (rc) {
- CERROR("ll_file_size: %d\n", rc);
- /* FIXME: need to somehow prevent inode creation */
- LBUG();
- make_bad_inode(inode);
- }
- }
-
- /* OIDEBUG(inode); */
-
- if (S_ISREG(inode->i_mode)) {
- inode->i_op = &ll_file_inode_operations;
- inode->i_fop = &ll_file_operations;
- inode->i_mapping->a_ops = &ll_aops;
- EXIT;
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &ll_dir_inode_operations;
- inode->i_fop = &ll_dir_operations;
- inode->i_mapping->a_ops = &ll_dir_aops;
- EXIT;
- } else if (S_ISLNK(inode->i_mode)) {
- inode->i_op = &ll_fast_symlink_inode_operations;
- EXIT;
- } else {
- init_special_inode(inode, inode->i_mode,
- kdev_t_to_nr(inode->i_rdev));
- EXIT;
- }
-
- return rc;
-}
-
-static inline void invalidate_request_list(struct list_head *req_list)
-{
- struct list_head *tmp, *n;
- list_for_each_safe(tmp, n, req_list) {
- struct ptlrpc_request *req =
- list_entry(tmp, struct ptlrpc_request, rq_list);
- CERROR("invalidating req xid %d op %d to %s:%d\n",
- (unsigned long long)req->rq_xid, req->rq_reqmsg->opc,
- req->rq_connection->c_remote_uuid,
- req->rq_import->imp_client->cli_request_portal);
- req->rq_flags |= PTL_RPC_FL_ERR;
- wake_up(&req->rq_wait_for_rep);
- }
-}
-
-void ll_umount_begin(struct super_block *sb)
-{
- struct ll_sb_info *sbi = ll_s2sbi(sb);
- struct list_head *ctmp;
-
- ENTRY;
-
- list_for_each(ctmp, &sbi->ll_conn_chain) {
- struct ptlrpc_connection *conn;
- conn = list_entry(ctmp, struct ptlrpc_connection, c_sb_chain);
-
- spin_lock(&conn->c_lock);
- conn->c_flags |= CONN_INVALID;
- invalidate_request_list(&conn->c_sending_head);
- invalidate_request_list(&conn->c_delayed_head);
- spin_unlock(&conn->c_lock);
- }
-
- EXIT;
-}
-
-
-static kmem_cache_t *ll_inode_cachep;
-
-static struct inode *ll_alloc_inode(struct super_block *sb)
-{
- struct ll_inode_info *lli;
- lli = kmem_cache_alloc(ll_inode_cachep, SLAB_KERNEL);
- if (!lli)
- return NULL;
-
- memset(lli, 0, (char *)&lli->lli_vfs_inode - (char *)lli);
- sema_init(&lli->lli_open_sem, 1);
-
- return &lli->lli_vfs_inode;
-}
-
-static void ll_destroy_inode(struct inode *inode)
-{
- kmem_cache_free(ll_inode_cachep, ll_i2info(inode));
-}
-
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
-{
- struct ll_inode_info *lli = foo;
-
- if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
- SLAB_CTOR_CONSTRUCTOR)
- inode_init_once(&lli->lli_vfs_inode);
-}
-
-int ll_init_inodecache(void)
-{
- ll_inode_cachep = kmem_cache_create("lustre_inode_cache",
- sizeof(struct ll_inode_info),
- 0, SLAB_HWCACHE_ALIGN,
- init_once, NULL);
- if (ll_inode_cachep == NULL)
- return -ENOMEM;
- return 0;
-}
-
-void ll_destroy_inodecache(void)
-{
- if (kmem_cache_destroy(ll_inode_cachep))
- CERROR("ll_inode_cache: not all structures were freed\n");
-}
-
-
-
-/* exported operations */
-struct super_operations ll_super_operations =
-{
- alloc_inode: ll_alloc_inode,
- destroy_inode: ll_destroy_inode,
- clear_inode: ll_clear_inode,
- delete_inode: ll_delete_inode,
- put_super: ll_put_super,
- statfs: ll_statfs,
- umount_begin: ll_umount_begin
-};
-
-struct file_system_type lustre_lite_fs_type = {
- .owner = THIS_MODULE,
- .name = "lustre_lite",
- .get_sb = ll_get_sb,
- .kill_sb = kill_litter_super,
-};
-
-static int __init init_lustre_lite(void)
-{
- int rc;
- printk(KERN_INFO "Lustre Lite 0.5.14, info@clusterfs.com\n");
- rc = ll_init_inodecache();
- if (rc)
- return -ENOMEM;
- ll_file_data_slab = kmem_cache_create("ll_file_data",
- sizeof(struct ll_file_data), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (ll_file_data_slab == NULL) {
- ll_destroy_inodecache();
- return -ENOMEM;
- }
- return register_filesystem(&lustre_lite_fs_type);
-}
-
-static void __exit exit_lustre_lite(void)
-{
- unregister_filesystem(&lustre_lite_fs_type);
- ll_destroy_inodecache();
- kmem_cache_destroy(ll_file_data_slab);
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Lite Client File System v1.0");
-MODULE_LICENSE("GPL");
-
-module_init(init_lustre_lite);
-module_exit(exit_lustre_lite);
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/stat.h>
-#include <linux/smp_lock.h>
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_lite.h>
-
-static int ll_readlink_internal(struct inode *inode,
- struct ptlrpc_request **request, char **symname)
-{
- struct ll_inode_info *lli = ll_i2info(inode);
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- int rc, symlen = inode->i_size + 1;
- ENTRY;
-
- *request = NULL;
-
- if (lli->lli_symlink_name) {
- *symname = lli->lli_symlink_name;
- CDEBUG(D_INODE, "using cached symlink %s\n", *symname);
- RETURN(0);
- }
-
- rc = mdc_getattr(&sbi->ll_mdc_conn, inode->i_ino, S_IFLNK,
- OBD_MD_LINKNAME, symlen, request);
- if (rc) {
- CERROR("inode "LPD64": rc = %d\n", inode->i_ino, rc);
- RETURN(rc);
- }
-
- *symname = lustre_msg_buf((*request)->rq_repmsg, 1);
-
- OBD_ALLOC(lli->lli_symlink_name, symlen);
- /* do not return an error if we cannot cache the symlink locally */
- if (lli->lli_symlink_name)
- memcpy(lli->lli_symlink_name, *symname, symlen);
-
- RETURN(0);
-}
-
-static int ll_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
- struct inode *inode = dentry->d_inode;
- struct ll_inode_info *lli = ll_i2info(inode);
- struct ptlrpc_request *request;
- char *symname;
- int rc;
- ENTRY;
-
- /* on symlinks lli_open_sem protects lli_symlink_name allocation/data */
- down(&lli->lli_open_sem);
- rc = ll_readlink_internal(inode, &request, &symname);
- if (rc)
- GOTO(out, rc);
-
- rc = vfs_readlink(dentry, buffer, buflen, symname);
- out:
- up(&lli->lli_open_sem);
- ptlrpc_req_finished(request);
-
- RETURN(rc);
-}
-
-static int ll_follow_link(struct dentry *dentry, struct nameidata *nd,
- struct lookup_intent *it)
-{
- struct inode *inode = dentry->d_inode;
- struct ll_inode_info *lli = ll_i2info(inode);
- struct ptlrpc_request *request;
- int op, mode;
- char *symname;
- int rc;
- ENTRY;
-
- op = it->it_op;
- mode = it->it_mode;
-
- ll_intent_release(dentry, it);
- down(&lli->lli_open_sem);
-
- it->it_op = op;
- it->it_mode = mode;
-
- rc = ll_readlink_internal(inode, &request, &symname);
- if (rc)
- GOTO(out, rc);
-
- rc = vfs_follow_link_it(nd, symname, it);
- out:
- up(&lli->lli_open_sem);
- ptlrpc_req_finished(request);
-
- RETURN(rc);
-}
-
-extern int ll_setattr(struct dentry *de, struct iattr *attr);
-struct inode_operations ll_fast_symlink_inode_operations = {
- readlink: ll_readlink,
- setattr: ll_setattr,
- follow_link2: ll_follow_link
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/sysctl.h>
-#include <linux/swapctl.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/ctype.h>
-#include <asm/bitops.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/utsname.h>
-
-struct ctl_table_header *ll_table_header = NULL;
-
-int ll_debug_level = 0;
-int ll_print_entry = 1;
-
-
-#define LL_SYSCTL 1
-
-#define LL_DEBUG 1 /* control debugging */
-#define LL_ENTRY 2 /* control enter/leave pattern */
-#define LL_TIMEOUT 3 /* timeout on upcalls to become intrble */
-#define LL_HARD 4 /* mount type "hard" or "soft" */
-#define LL_VARS 5
-#define LL_INDEX 6
-#define LL_RESET 7
-
-#define LL_VARS_SLOT 2
-
-static ctl_table ll_table[] = {
- {LL_DEBUG, "debug", &ll_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
- {LL_ENTRY, "trace", &ll_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
- { 0 }
-};
-
-static ctl_table top_table[] = {
- {LL_SYSCTL, "lustre_light", NULL, 0, 0555, ll_table},
- {0}
-};
-
-void ll_sysctl_init (void)
-{
-
-#ifdef CONFIG_SYSCTL
- if ( !ll_table_header )
- ll_table_header = register_sysctl_table(top_table, 0);
-#endif
-}
-
-void ll_sysctl_clean (void)
-{
-#ifdef CONFIG_SYSCTL
- if ( ll_table_header )
- unregister_sysctl_table(ll_table_header);
- ll_table_header = NULL;
-#endif
-}
+++ /dev/null
-.deps
-Makefile
-Makefile.in
+++ /dev/null
-# Copyright (C) 2002 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=
-
-MODULE = lov
-modulefs_DATA = lov.o
-EXTRA_PROGRAMS = lov
-LINX=
-
-lov_SOURCES = lov_obd.c lov_pack.c lproc_lov.c $(LINX)
-
-include $(top_srcdir)/Rules
+++ /dev/null
- /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * lov/lov.c
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * Author: Phil Schwan <phil@off.net>
- * Peter Braam <braam@clusterfs.com>
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_LOV
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/obd_support.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_net.h>
-#include <linux/lustre_idl.h>
-#include <linux/lustre_mds.h>
-#include <linux/obd_class.h>
-#include <linux/obd_lov.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <asm/div64.h>
-#include <linux/lprocfs_status.h>
-
-extern struct lprocfs_vars status_var_nm_1[];
-extern struct lprocfs_vars status_class_var[];
-
-static kmem_cache_t *lov_file_cache;
-
-struct lov_file_handles {
- struct list_head lfh_list;
- __u64 lfh_cookie;
- int lfh_count;
- struct lustre_handle *lfh_handles;
-};
-
-extern int lov_packmd(struct lustre_handle *conn, struct lov_mds_md **lmm,
- struct lov_stripe_md *lsm);
-extern int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsm,
- struct lov_mds_md *lmm);
-
-/* obd methods */
-int lov_attach(struct obd_device *dev, obd_count len, void *data)
-{
- return lprocfs_reg_obd(dev, status_var_nm_1, dev);
-}
-
-int lov_detach(struct obd_device *dev)
-{
- return lprocfs_dereg_obd(dev);
-}
-
-static int lov_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- struct ptlrpc_request *req = NULL;
- struct lov_obd *lov = &obd->u.lov;
- struct client_obd *mdc = &lov->mdcobd->u.cli;
- struct lov_desc *desc = &lov->desc;
- struct obd_export *exp;
- struct lustre_handle mdc_conn;
- obd_uuid_t *uuidarray;
- int rc, rc2, i;
- ENTRY;
-
- MOD_INC_USE_COUNT;
- rc = class_connect(conn, obd, cluuid);
- if (rc)
- GOTO(out_dec, rc);
-
- /* We don't want to actually do the underlying connections more than
- * once, so keep track. */
- lov->refcount++;
- if (lov->refcount > 1)
- RETURN(0);
-
- exp = class_conn2export(conn);
- INIT_LIST_HEAD(&exp->exp_lov_data.led_open_head);
-
- /* retrieve LOV metadata from MDS */
- rc = obd_connect(&mdc_conn, lov->mdcobd, NULL, recovd, recover);
- if (rc) {
- CERROR("cannot connect to mdc: rc = %d\n", rc);
- GOTO(out_conn, rc);
- }
-
- rc = mdc_getlovinfo(obd, &mdc_conn, &req);
- rc2 = obd_disconnect(&mdc_conn);
- if (rc) {
- CERROR("cannot get lov info %d\n", rc);
- GOTO(out_conn, rc);
- }
-
- if (rc2) {
- CERROR("error disconnecting from MDS %d\n", rc2);
- GOTO(out_conn, rc = rc2);
- }
-
- /* sanity... */
- if (req->rq_repmsg->bufcount < 2 ||
- req->rq_repmsg->buflens[0] < sizeof(*desc)) {
- CERROR("LOV desc: invalid descriptor returned\n");
- GOTO(out_conn, rc = -EINVAL);
- }
-
- memcpy(desc, lustre_msg_buf(req->rq_repmsg, 0), sizeof(*desc));
- lov_unpackdesc(desc);
-
- if (req->rq_repmsg->buflens[1] < sizeof(*uuidarray)*desc->ld_tgt_count){
- CERROR("LOV desc: invalid uuid array returned\n");
- GOTO(out_conn, rc = -EINVAL);
- }
-
- if (memcmp(obd->obd_uuid, desc->ld_uuid, sizeof(desc->ld_uuid))) {
- CERROR("LOV desc: uuid %s not on mds device (%s)\n",
- obd->obd_uuid, desc->ld_uuid);
- GOTO(out_conn, rc = -EINVAL);
- }
-
- if (desc->ld_tgt_count > 1000) {
- CERROR("LOV desc: target count > 1000 (%d)\n",
- desc->ld_tgt_count);
- GOTO(out_conn, rc = -EINVAL);
- }
-
- /* Because of 64-bit divide/mod operations only work with a 32-bit
- * divisor in a 32-bit kernel, we cannot support a stripe width
- * of 4GB or larger on 32-bit CPUs.
- */
- if ((desc->ld_default_stripe_count ?
- desc->ld_default_stripe_count : desc->ld_tgt_count) *
- desc->ld_default_stripe_size > ~0UL) {
- CERROR("LOV: stripe width "LPU64"x%u > %lu on 32-bit system\n",
- desc->ld_default_stripe_size,
- desc->ld_default_stripe_count ?
- desc->ld_default_stripe_count : desc->ld_tgt_count,~0UL);
- GOTO(out_conn, rc = -EINVAL);
- }
-
- lov->bufsize = sizeof(struct lov_tgt_desc) * desc->ld_tgt_count;
- OBD_ALLOC(lov->tgts, lov->bufsize);
- if (!lov->tgts) {
- CERROR("Out of memory\n");
- GOTO(out_conn, rc = -ENOMEM);
- }
-
- uuidarray = lustre_msg_buf(req->rq_repmsg, 1);
- for (i = 0; i < desc->ld_tgt_count; i++)
- memcpy(lov->tgts[i].uuid, uuidarray[i], sizeof(*uuidarray));
-
- for (i = 0; i < desc->ld_tgt_count; i++) {
- struct obd_device *tgt = class_uuid2obd(uuidarray[i]);
- int rc2;
-
- if (!tgt) {
- CERROR("Target %s not attached\n", uuidarray[i]);
- GOTO(out_disc, rc = -EINVAL);
- }
-
- if (!(tgt->obd_flags & OBD_SET_UP)) {
- CERROR("Target %s not set up\n", uuidarray[i]);
- GOTO(out_disc, rc = -EINVAL);
- }
-
- rc = obd_connect(&lov->tgts[i].conn, tgt, NULL, recovd,
- recover);
-
- /* Register even if connect failed, so that we get reactivation
- * notices.
- */
- rc2 = obd_iocontrol(IOC_OSC_REGISTER_LOV, &lov->tgts[i].conn,
- sizeof(struct obd_device *), obd, NULL);
- if (rc2) {
- CERROR("Target %s REGISTER_LOV error %d\n",
- uuidarray[i], rc2);
- GOTO(out_disc, rc2);
- }
-
- /* But mark failed-connect OSCs as inactive! */
- if (rc) {
- CDEBUG(D_INFO, "Target %s connect error %d\n",
- uuidarray[i], rc);
- LASSERT(lov->tgts[i].active == 0);
- rc = 0;
- continue;
- }
-
- desc->ld_active_tgt_count++;
- lov->tgts[i].active = 1;
- }
-
- mdc->cl_max_mds_easize = obd_size_wiremd(conn, NULL);
-
- out:
- ptlrpc_req_finished(req);
- RETURN(rc);
-
- out_disc:
- while (i-- > 0) {
- desc->ld_active_tgt_count--;
- lov->tgts[i].active = 0;
- rc2 = obd_disconnect(&lov->tgts[i].conn);
- if (rc2)
- CERROR("LOV Target %s disconnect error: rc = %d\n",
- uuidarray[i], rc2);
- }
- OBD_FREE(lov->tgts, lov->bufsize);
- out_conn:
- class_disconnect(conn);
- out_dec:
- MOD_DEC_USE_COUNT;
- goto out;
-}
-
-static int lov_disconnect(struct lustre_handle *conn)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct lov_obd *lov = &obd->u.lov;
- struct obd_export *exp;
- struct list_head *p, *n;
- int rc, i;
-
- if (!lov->tgts)
- goto out_local;
-
- /* Only disconnect the underlying layers on the final disconnect. */
- lov->refcount--;
- if (lov->refcount != 0)
- goto out_local;
-
- for (i = 0; i < lov->desc.ld_tgt_count; i++) {
- rc = obd_disconnect(&lov->tgts[i].conn);
- if (rc) {
- if (lov->tgts[i].active) {
- CERROR("Target %s disconnect error %d\n",
- lov->tgts[i].uuid, rc);
- }
- rc = 0;
- }
- if (lov->tgts[i].active) {
- lov->desc.ld_active_tgt_count--;
- lov->tgts[i].active = 0;
- }
- }
- OBD_FREE(lov->tgts, lov->bufsize);
- lov->bufsize = 0;
- lov->tgts = NULL;
-
- exp = class_conn2export(conn);
- list_for_each_safe(p, n, &exp->exp_lov_data.led_open_head) {
- /* XXX close these, instead of just discarding them? */
- struct lov_file_handles *lfh;
- lfh = list_entry(p, typeof(*lfh), lfh_list);
- CERROR("discarding open LOV handle %p:"LPX64"\n",
- lfh, lfh->lfh_cookie);
- list_del(&lfh->lfh_list);
- OBD_FREE(lfh->lfh_handles,
- lfh->lfh_count * sizeof(*lfh->lfh_handles));
- kmem_cache_free(lov_file_cache, lfh);
- }
-
- out_local:
- rc = class_disconnect(conn);
- if (!rc)
- MOD_DEC_USE_COUNT;
- return rc;
-}
-
-/* Error codes:
- *
- * -EINVAL : UUID can't be found in the LOV's target list
- * -ENOTCONN: The UUID is found, but the target connection is bad (!)
- * -EBADF : The UUID is found, but the OBD is the wrong type (!)
- * -EALREADY: The OSC is already marked (in)active
- */
-static int lov_set_osc_active(struct lov_obd *lov, obd_uuid_t uuid,
- int activate)
-{
- struct obd_device *obd;
- int i, rc = 0;
- ENTRY;
-
- CDEBUG(D_INFO, "Searching in lov %p for uuid %s (activate=%d)\n",
- lov, uuid, activate);
-
- spin_lock(&lov->lov_lock);
- for (i = 0; i < lov->desc.ld_tgt_count; i++)
- if (strncmp(uuid, lov->tgts[i].uuid,
- sizeof(lov->tgts[i].uuid)) == 0)
- break;
-
- if (i == lov->desc.ld_tgt_count)
- GOTO(out, rc = -EINVAL);
-
- obd = class_conn2obd(&lov->tgts[i].conn);
- if (obd == NULL) {
- LBUG();
- GOTO(out, rc = -ENOTCONN);
- }
-
- CDEBUG(D_INFO, "Found OBD %p type %s\n", obd, obd->obd_type->typ_name);
- if (strcmp(obd->obd_type->typ_name, "osc") != 0) {
- LBUG();
- GOTO(out, rc = -EBADF);
- }
-
- if (lov->tgts[i].active == activate) {
- CDEBUG(D_INFO, "OBD %p already %sactive!\n", obd,
- activate ? "" : "in");
- GOTO(out, rc = -EALREADY);
- }
-
- CDEBUG(D_INFO, "Marking OBD %p %sactive\n", obd, activate ? "" : "in");
-
- lov->tgts[i].active = activate;
- if (activate) {
- /*
- * foreach(export)
- * foreach(open_file)
- * if (file_handle uses this_osc)
- * if (has_no_filehandle)
- * open(file_handle, this_osc);
- */
- /* XXX reconnect? */
- lov->desc.ld_active_tgt_count++;
- } else {
- /*
- * Should I invalidate filehandles that refer to this OSC, so
- * that I reopen them during reactivation?
- */
- /* XXX disconnect from OSC? */
- lov->desc.ld_active_tgt_count--;
- }
-
- EXIT;
- out:
- spin_unlock(&lov->lov_lock);
- return rc;
-}
-
-static int lov_setup(struct obd_device *obd, obd_count len, void *buf)
-{
- struct obd_ioctl_data *data = buf;
- struct lov_obd *lov = &obd->u.lov;
- int rc = 0;
- ENTRY;
-
- if (data->ioc_inllen1 < 1) {
- CERROR("LOV setup requires an MDC UUID\n");
- RETURN(-EINVAL);
- }
-
- if (data->ioc_inllen1 > 37) {
- CERROR("mdc UUID must be 36 characters or less\n");
- RETURN(-EINVAL);
- }
-
- spin_lock_init(&lov->lov_lock);
- lov->mdcobd = class_uuid2obd(data->ioc_inlbuf1);
- if (!lov->mdcobd) {
- CERROR("LOV %s cannot locate MDC %s\n", obd->obd_uuid,
- data->ioc_inlbuf1);
- rc = -EINVAL;
- }
- RETURN(rc);
-}
-
-static struct lov_file_handles *lov_handle2lfh(struct lustre_handle *handle)
-{
- struct lov_file_handles *lfh = NULL;
-
- if (!handle || !handle->addr)
- RETURN(NULL);
-
- lfh = (struct lov_file_handles *)(unsigned long)(handle->addr);
- if (!kmem_cache_validate(lov_file_cache, lfh))
- RETURN(NULL);
-
- if (lfh->lfh_cookie != handle->cookie)
- RETURN(NULL);
-
- return lfh;
-}
-
-/* the LOV expects oa->o_id to be set to the LOV object id */
-static int lov_create(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md **ea)
-{
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct lov_stripe_md *lsm;
- struct lov_oinfo *loi;
- struct obdo *tmp;
- int ost_count, ost_idx = 1;
- int rc = 0, i;
- ENTRY;
-
- LASSERT(ea);
-
- if (!export)
- RETURN(-EINVAL);
-
- tmp = obdo_alloc();
- if (!tmp)
- RETURN(-ENOMEM);
-
- lov = &export->exp_obd->u.lov;
-
- if (!lov->desc.ld_active_tgt_count)
- RETURN(-EIO);
-
- spin_lock(&lov->lov_lock);
- ost_count = lov->desc.ld_tgt_count;
-
- lsm = *ea;
-
- /* Can't create more stripes than we have targets (incl inactive). */
- if (lsm && lsm->lsm_stripe_count > lov->desc.ld_tgt_count)
- GOTO(out_tmp, rc = -EINVAL);
-
- /* Free the user lsm if it needs to be changed, to avoid memory leaks */
- if (!lsm || (lsm &&
- lsm->lsm_stripe_count > lov->desc.ld_active_tgt_count)) {
- struct lov_stripe_md *lsm_new = NULL;
- rc = obd_alloc_memmd(conn, &lsm_new);
- if (rc < 0) {
- spin_unlock(&lov->lov_lock);
- if (lsm)
- obd_free_memmd(conn, &lsm);
- GOTO(out_tmp, rc);
- }
- if (lsm) {
- LASSERT(lsm->lsm_magic == LOV_MAGIC);
- CERROR("replace user LOV MD: stripes %u > %u active\n",
- lsm->lsm_stripe_count,
- lov->desc.ld_active_tgt_count);
- lsm_new->lsm_stripe_offset = lsm->lsm_stripe_offset;
- lsm_new->lsm_stripe_size = lsm->lsm_stripe_size;
- lsm_new->lsm_stripe_pattern = lsm->lsm_stripe_pattern;
- obd_free_memmd(conn, &lsm);
- }
- lsm = lsm_new;
- ost_idx = 0; /* if lsm->lsm_stripe_offset is set yet */
- lsm->lsm_magic = LOV_MAGIC;
- }
-
- LASSERT(oa->o_valid & OBD_MD_FLID);
- lsm->lsm_object_id = oa->o_id;
- if (!lsm->lsm_stripe_size)
- lsm->lsm_stripe_size = lov->desc.ld_default_stripe_size;
-
- /* Because of 64-bit divide/mod operations only work with a 32-bit
- * divisor in a 32-bit kernel, we cannot support a stripe width
- * of 4GB or larger on 32-bit CPUs.
- */
- if (lsm->lsm_stripe_size * lsm->lsm_stripe_count > ~0UL) {
- CERROR("LOV: stripe width "LPU64"x%u > %lu on 32-bit system\n",
- lsm->lsm_stripe_size, lsm->lsm_stripe_count, ~0UL);
- spin_unlock(&lov->lov_lock);
- GOTO(out_free, rc = -EINVAL);
- }
-
- if (!ost_idx || lsm->lsm_stripe_offset >= ost_count) {
- int mult = lsm->lsm_object_id * lsm->lsm_stripe_count;
- int stripe_offset = mult % ost_count;
- int sub_offset = (mult / ost_count) % lsm->lsm_stripe_count;
-
- lsm->lsm_stripe_offset = stripe_offset + sub_offset;
- }
-
- /* Start with lsm_stripe_offset on an active OSC to avoid confusion */
- while (!lov->tgts[lsm->lsm_stripe_offset].active)
- lsm->lsm_stripe_offset = (lsm->lsm_stripe_offset+1) % ost_count;
-
- /* Pick the OSTs before we release the lock */
- ost_idx = lsm->lsm_stripe_offset;
- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
- CDEBUG(D_INODE, "objid "LPX64"[%d] is ost_idx %d (uuid %s)\n",
- lsm->lsm_object_id, i, ost_idx, lov->tgts[ost_idx].uuid);
- loi->loi_ost_idx = ost_idx;
- do {
- ost_idx = (ost_idx + 1) % ost_count;
- } while (!lov->tgts[ost_idx].active);
- }
-
- spin_unlock(&lov->lov_lock);
-
- CDEBUG(D_INODE, "allocating %d subobjs for objid "LPX64" at idx %d\n",
- lsm->lsm_stripe_count,lsm->lsm_object_id,lsm->lsm_stripe_offset);
-
- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
- struct lov_stripe_md obj_md;
- struct lov_stripe_md *obj_mdp = &obj_md;
-
- ost_idx = loi->loi_ost_idx;
-
- /* create data objects with "parent" OA */
- memcpy(tmp, oa, sizeof(*tmp));
- /* XXX: LOV STACKING: use real "obj_mdp" sub-data */
- rc = obd_create(&lov->tgts[ost_idx].conn, tmp, &obj_mdp);
- if (rc) {
- CERROR("error creating objid "LPX64" sub-object on "
- "OST idx %d: rc = %d\n", oa->o_id, ost_idx, rc);
- GOTO(out_cleanup, rc);
- }
- loi->loi_id = tmp->o_id;
- CDEBUG(D_INODE, "objid "LPX64" has subobj "LPX64" at idx %d\n",
- lsm->lsm_object_id, loi->loi_id, ost_idx);
- }
-
- *ea = lsm;
-
- out_tmp:
- obdo_free(tmp);
- RETURN(rc);
-
- out_cleanup:
- while (i-- > 0) {
- int err;
-
- --loi;
- /* destroy already created objects here */
- memcpy(tmp, oa, sizeof(*tmp));
- tmp->o_id = loi->loi_id;
- err = obd_destroy(&lov->tgts[loi->loi_ost_idx].conn, tmp, NULL);
- if (err)
- CERROR("Failed to uncreate objid "LPX64" subobj "
- LPX64" on OST idx %d: rc = %d\n",
- oa->o_id, loi->loi_id, loi->loi_ost_idx,
- err);
- }
- out_free:
- if (!*ea)
- obd_free_memmd(conn, &lsm);
- goto out_tmp;
-}
-
-static int lov_destroy(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm)
-{
- struct obdo tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct lov_oinfo *loi;
- struct lov_file_handles *lfh = NULL;
- int rc = 0, i;
- ENTRY;
-
- if (!lsm) {
- CERROR("LOV requires striping ea for destruction\n");
- RETURN(-EINVAL);
- }
-
- if (lsm->lsm_magic != LOV_MAGIC) {
- CERROR("LOV striping magic bad %#lx != %#lx\n",
- lsm->lsm_magic, LOV_MAGIC);
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- if (oa->o_valid & OBD_MD_FLHANDLE)
- lfh = lov_handle2lfh(obdo_handle(oa));
-
- lov = &export->exp_obd->u.lov;
- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
- int err;
- if (lov->tgts[loi->loi_ost_idx].active == 0) {
- /* Orphan clean up will (someday) fix this up. */
- continue;
- }
-
- memcpy(&tmp, oa, sizeof(tmp));
- tmp.o_id = loi->loi_id;
- if (lfh)
- memcpy(obdo_handle(&tmp), &lfh->lfh_handles[i],
- sizeof(lfh->lfh_handles[i]));
- else
- tmp.o_valid &= ~OBD_MD_FLHANDLE;
- err = obd_destroy(&lov->tgts[loi->loi_ost_idx].conn, &tmp,
- NULL);
- if (err && lov->tgts[loi->loi_ost_idx].active) {
- CERROR("Error destroying objid "LPX64" subobj "
- LPX64" on OST idx %d\n: rc = %d",
- oa->o_id, loi->loi_id, loi->loi_ost_idx, err);
- if (!rc)
- rc = err;
- }
- }
- RETURN(rc);
-}
-
-/* compute object size given "stripeno" and the ost size */
-static obd_size lov_stripe_size(struct lov_stripe_md *lsm, obd_size ost_size,
- int stripeno)
-{
- unsigned long ssize = lsm->lsm_stripe_size;
- unsigned long swidth = ssize * lsm->lsm_stripe_count;
- unsigned long stripe_size;
- obd_size lov_size;
-
- if (ost_size == 0)
- return 0;
-
- /* do_div(a, b) returns a % b, and a = a / b */
- stripe_size = do_div(ost_size, ssize);
-
- if (stripe_size)
- lov_size = ost_size * swidth + stripeno * ssize + stripe_size;
- else
- lov_size = (ost_size - 1) * swidth + (stripeno + 1) * ssize;
-
- return lov_size;
-}
-
-static void lov_merge_attrs(struct obdo *tgt, struct obdo *src, obd_flag valid,
- struct lov_stripe_md *lsm, int stripeno, int *new)
-{
- if (*new) {
- obdo_cpy_md(tgt, src, valid);
- if (valid & OBD_MD_FLSIZE)
- tgt->o_size = lov_stripe_size(lsm,src->o_size,stripeno);
- *new = 0;
- } else {
- if (valid & OBD_MD_FLSIZE) {
- /* this handles sparse files properly */
- obd_size lov_size;
-
- lov_size = lov_stripe_size(lsm, src->o_size, stripeno);
- if (lov_size > tgt->o_size)
- tgt->o_size = lov_size;
- }
- if (valid & OBD_MD_FLBLOCKS)
- tgt->o_blocks += src->o_blocks;
- if (valid & OBD_MD_FLCTIME && tgt->o_ctime < src->o_ctime)
- tgt->o_ctime = src->o_ctime;
- if (valid & OBD_MD_FLMTIME && tgt->o_mtime < src->o_mtime)
- tgt->o_mtime = src->o_mtime;
- }
-}
-
-static int lov_getattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm)
-{
- struct obdo tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct lov_oinfo *loi;
- struct lov_file_handles *lfh = NULL;
- int i;
- int new = 1;
- ENTRY;
-
- if (!lsm) {
- CERROR("LOV requires striping ea\n");
- RETURN(-EINVAL);
- }
-
- if (lsm->lsm_magic != LOV_MAGIC) {
- CERROR("LOV striping magic bad %#lx != %#lx\n",
- lsm->lsm_magic, LOV_MAGIC);
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- lov = &export->exp_obd->u.lov;
-
- if (oa->o_valid & OBD_MD_FLHANDLE)
- lfh = lov_handle2lfh(obdo_handle(oa));
-
- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
- int err;
-
- if (loi->loi_id == 0)
- continue;
-
- if (lov->tgts[loi->loi_ost_idx].active == 0)
- continue;
-
- CDEBUG(D_INFO, "objid "LPX64"[%d] has subobj "LPX64" at idx "
- "%u\n", oa->o_id, i, loi->loi_id, loi->loi_ost_idx);
- /* create data objects with "parent" OA */
- memcpy(&tmp, oa, sizeof(tmp));
- tmp.o_id = loi->loi_id;
- if (lfh)
- memcpy(obdo_handle(&tmp), &lfh->lfh_handles[i],
- sizeof(lfh->lfh_handles[i]));
- else
- tmp.o_valid &= ~OBD_MD_FLHANDLE;
-
- err = obd_getattr(&lov->tgts[loi->loi_ost_idx].conn, &tmp,NULL);
- if (err && lov->tgts[loi->loi_ost_idx].active) {
- CERROR("Error getattr objid "LPX64" subobj "LPX64
- " on OST idx %d: rc = %d\n",
- oa->o_id, loi->loi_id, loi->loi_ost_idx, err);
- RETURN(err);
- }
- lov_merge_attrs(oa, &tmp, tmp.o_valid, lsm, i, &new);
- }
-
- RETURN(0);
-}
-
-static int lov_setattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm)
-{
- struct obdo *tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct lov_oinfo *loi;
- struct lov_file_handles *lfh = NULL;
- int rc = 0, i;
- ENTRY;
-
- /* Note that this code is currently unused, hence LBUG(), just
- * to know when/if it is ever revived that it needs cleanups.
- */
- LBUG();
-
- if (!lsm) {
- CERROR("LOV requires striping ea\n");
- RETURN(-EINVAL);
- }
-
- if (lsm->lsm_magic != LOV_MAGIC) {
- CERROR("LOV striping magic bad %#lx != %#lx\n",
- lsm->lsm_magic, LOV_MAGIC);
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- /* size changes should go through punch and not setattr */
- LASSERT(!(oa->o_valid & OBD_MD_FLSIZE));
-
- tmp = obdo_alloc();
- if (!tmp)
- RETURN(-ENOMEM);
-
- if (oa->o_valid & OBD_MD_FLHANDLE)
- lfh = lov_handle2lfh(obdo_handle(oa));
-
- lov = &export->exp_obd->u.lov;
- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
- int err;
-
- obdo_cpy_md(tmp, oa, oa->o_valid);
-
- if (lfh)
- memcpy(obdo_handle(tmp), &lfh->lfh_handles[i],
- sizeof(lfh->lfh_handles[i]));
- else
- tmp->o_valid &= ~OBD_MD_FLHANDLE;
-
- tmp->o_id = loi->loi_id;
-
- err = obd_setattr(&lov->tgts[loi->loi_ost_idx].conn, tmp, NULL);
- if (err) {
- CERROR("Error setattr objid "LPX64" subobj "LPX64
- " on OST idx %d: rc = %d\n",
- oa->o_id, loi->loi_id, loi->loi_ost_idx, err);
- if (!rc)
- rc = err;
- }
- }
- obdo_free(tmp);
- RETURN(rc);
-}
-
-static int lov_open(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm)
-{
- struct obdo *tmp; /* on the heap here, on the stack in lov_close? */
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct lov_oinfo *loi;
- struct lov_file_handles *lfh = NULL;
- struct lustre_handle *handle;
- int new = 1;
- int rc = 0, i;
- ENTRY;
-
- if (!lsm) {
- CERROR("LOV requires striping ea for opening\n");
- RETURN(-EINVAL);
- }
-
- if (lsm->lsm_magic != LOV_MAGIC) {
- CERROR("LOV striping magic bad %#lx != %#lx\n",
- lsm->lsm_magic, LOV_MAGIC);
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- tmp = obdo_alloc();
- if (!tmp)
- RETURN(-ENOMEM);
-
- lfh = kmem_cache_alloc(lov_file_cache, GFP_KERNEL);
- if (!lfh)
- GOTO(out_tmp, rc = -ENOMEM);
- OBD_ALLOC(lfh->lfh_handles,
- lsm->lsm_stripe_count * sizeof(*lfh->lfh_handles));
- if (!lfh->lfh_handles)
- GOTO(out_lfh, rc = -ENOMEM);
-
- lov = &export->exp_obd->u.lov;
- oa->o_size = 0;
- oa->o_blocks = 0;
- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
-
- if (lov->tgts[loi->loi_ost_idx].active == 0) {
- continue;
- }
-
- /* create data objects with "parent" OA */
- memcpy(tmp, oa, sizeof(*tmp));
- tmp->o_id = loi->loi_id;
-
- rc = obd_open(&lov->tgts[loi->loi_ost_idx].conn, tmp, NULL);
- if (rc && lov->tgts[loi->loi_ost_idx].active) {
- CERROR("Error open objid "LPX64" subobj "LPX64
- " on OST idx %d: rc = %d\n",
- oa->o_id, lsm->lsm_oinfo[i].loi_id,
- loi->loi_ost_idx, rc);
- goto out_handles;
- }
-
- lov_merge_attrs(oa, tmp, tmp->o_valid, lsm, i, &new);
-
- if (tmp->o_valid & OBD_MD_FLHANDLE)
- memcpy(&lfh->lfh_handles[i], obdo_handle(tmp),
- sizeof(lfh->lfh_handles[i]));
- }
-
- handle = obdo_handle(oa);
-
- lfh->lfh_count = lsm->lsm_stripe_count;
- get_random_bytes(&lfh->lfh_cookie, sizeof(lfh->lfh_cookie));
-
- handle->addr = (__u64)(unsigned long)lfh;
- handle->cookie = lfh->lfh_cookie;
- oa->o_valid |= OBD_MD_FLHANDLE;
- list_add(&lfh->lfh_list, &export->exp_lov_data.led_open_head);
-
-out_tmp:
- obdo_free(tmp);
- RETURN(rc);
-
-out_handles:
- for (i--, loi = &lsm->lsm_oinfo[i]; i >= 0; i--, loi--) {
- int err;
-
- if (lov->tgts[loi->loi_ost_idx].active == 0)
- continue;
-
- memcpy(tmp, oa, sizeof(*tmp));
- tmp->o_id = loi->loi_id;
- memcpy(obdo_handle(tmp), &lfh->lfh_handles[i],
- sizeof(lfh->lfh_handles[i]));
-
- err = obd_close(&lov->tgts[loi->loi_ost_idx].conn, tmp, NULL);
- if (err) {
- CERROR("Error closing objid "LPX64" subobj "LPX64
- " on OST idx %d after open error: rc = %d\n",
- oa->o_id, loi->loi_id, loi->loi_ost_idx, err);
- }
- }
-
- OBD_FREE(lfh->lfh_handles,
- lsm->lsm_stripe_count * sizeof(*lfh->lfh_handles));
-out_lfh:
- lfh->lfh_cookie = DEAD_HANDLE_MAGIC;
- kmem_cache_free(lov_file_cache, lfh);
- goto out_tmp;
-}
-
-static int lov_close(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm)
-{
- struct obdo tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct lov_oinfo *loi;
- struct lov_file_handles *lfh = NULL;
- int rc = 0, i;
- ENTRY;
-
- if (!lsm) {
- CERROR("LOV requires striping ea\n");
- RETURN(-EINVAL);
- }
-
- if (lsm->lsm_magic != LOV_MAGIC) {
- CERROR("LOV striping magic bad %#lx != %#lx\n",
- lsm->lsm_magic, LOV_MAGIC);
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- if (oa->o_valid & OBD_MD_FLHANDLE)
- lfh = lov_handle2lfh(obdo_handle(oa));
-
- lov = &export->exp_obd->u.lov;
- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
- int err;
-
- if (lov->tgts[loi->loi_ost_idx].active == 0)
- continue;
-
- /* create data objects with "parent" OA */
- memcpy(&tmp, oa, sizeof(tmp));
- tmp.o_id = loi->loi_id;
- if (lfh)
- memcpy(obdo_handle(&tmp), &lfh->lfh_handles[i],
- sizeof(lfh->lfh_handles[i]));
- else
- tmp.o_valid &= ~OBD_MD_FLHANDLE;
-
- err = obd_close(&lov->tgts[loi->loi_ost_idx].conn, &tmp, NULL);
- if (err) {
- CERROR("Error close objid "LPX64" subobj "LPX64
- " on OST idx %d: rc = %d\n",
- oa->o_id, loi->loi_id, loi->loi_ost_idx, err);
- if (!rc)
- rc = err;
- }
- }
- if (lfh) {
- list_del(&lfh->lfh_list);
- OBD_FREE(lfh->lfh_handles,
- lsm->lsm_stripe_count * sizeof(*lfh->lfh_handles));
- lfh->lfh_cookie = DEAD_HANDLE_MAGIC;
- kmem_cache_free(lov_file_cache, lfh);
- }
-
- RETURN(rc);
-}
-
-#ifndef log2
-#define log2(n) ffz(~(n))
-#endif
-
-#warning FIXME: merge these two functions now that they are nearly the same
-
-/* compute ost offset in stripe "stripeno" corresponding to offset "lov_off" */
-static obd_off lov_stripe_offset(struct lov_stripe_md *lsm, obd_off lov_off,
- int stripeno)
-{
- unsigned long ssize = lsm->lsm_stripe_size;
- unsigned long swidth = ssize * lsm->lsm_stripe_count;
- unsigned long stripe_off, this_stripe;
-
- if (lov_off == OBD_OBJECT_EOF || lov_off == 0)
- return lov_off;
-
- /* do_div(a, b) returns a % b, and a = a / b */
- stripe_off = do_div(lov_off, swidth);
-
- this_stripe = stripeno * ssize;
- if (stripe_off <= this_stripe)
- stripe_off = 0;
- else {
- stripe_off -= this_stripe;
-
- if (stripe_off > ssize)
- stripe_off = ssize;
- }
-
-
- return lov_off * ssize + stripe_off;
-}
-
-/* compute which stripe number "lov_off" will be written into */
-static int lov_stripe_number(struct lov_stripe_md *lsm, obd_off lov_off)
-{
- unsigned long ssize = lsm->lsm_stripe_size;
- unsigned long swidth = ssize * lsm->lsm_stripe_count;
- unsigned long stripe_off;
-
- stripe_off = do_div(lov_off, swidth);
-
- return stripe_off / ssize;
-}
-
-
-/* FIXME: maybe we'll just make one node the authoritative attribute node, then
- * we can send this 'punch' to just the authoritative node and the nodes
- * that the punch will affect. */
-static int lov_punch(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm,
- obd_off start, obd_off end)
-{
- struct obdo tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct lov_oinfo *loi;
- struct lov_file_handles *lfh = NULL;
- int rc = 0, i;
- ENTRY;
-
- if (!lsm) {
- CERROR("LOV requires striping ea\n");
- RETURN(-EINVAL);
- }
-
- if (lsm->lsm_magic != LOV_MAGIC) {
- CERROR("LOV striping magic bad %#lx != %#lx\n",
- lsm->lsm_magic, LOV_MAGIC);
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- if (oa->o_valid & OBD_MD_FLHANDLE)
- lfh = lov_handle2lfh(obdo_handle(oa));
-
- lov = &export->exp_obd->u.lov;
- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
- obd_off starti = lov_stripe_offset(lsm, start, i);
- obd_off endi = lov_stripe_offset(lsm, end, i);
- int err;
-
- if (starti == endi)
- continue;
- /* create data objects with "parent" OA */
- memcpy(&tmp, oa, sizeof(tmp));
- tmp.o_id = loi->loi_id;
- if (lfh)
- memcpy(obdo_handle(&tmp), &lfh->lfh_handles[i],
- sizeof(lfh->lfh_handles[i]));
- else
- tmp.o_valid &= ~OBD_MD_FLHANDLE;
-
- err = obd_punch(&lov->tgts[loi->loi_ost_idx].conn, &tmp, NULL,
- starti, endi);
- if (err) {
- CERROR("Error punch objid "LPX64" subobj "LPX64
- " on OST idx %d: rc = %d\n",
- oa->o_id, loi->loi_id, loi->loi_ost_idx, err);
- if (!rc)
- rc = err;
- }
- }
- RETURN(rc);
-}
-
-static inline int lov_brw(int cmd, struct lustre_handle *conn,
- struct lov_stripe_md *lsm, obd_count oa_bufs,
- struct brw_page *pga, struct obd_brw_set *set)
-{
- struct {
- int bufct;
- int index;
- int subcount;
- struct lov_stripe_md lsm;
- int ost_idx;
- } *stripeinfo, *si, *si_last;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct brw_page *ioarr;
- struct lov_oinfo *loi;
- int rc = 0, i, *where, stripe_count = lsm->lsm_stripe_count;
- ENTRY;
-
- if (!lsm) {
- CERROR("LOV requires striping ea\n");
- RETURN(-EINVAL);
- }
-
- if (lsm->lsm_magic != LOV_MAGIC) {
- CERROR("LOV striping magic bad %#lx != %#lx\n",
- lsm->lsm_magic, LOV_MAGIC);
- RETURN(-EINVAL);
- }
-
- lov = &export->exp_obd->u.lov;
-
- OBD_ALLOC(stripeinfo, stripe_count * sizeof(*stripeinfo));
- if (!stripeinfo)
- GOTO(out_cbdata, rc = -ENOMEM);
-
- OBD_ALLOC(where, sizeof(*where) * oa_bufs);
- if (!where)
- GOTO(out_sinfo, rc = -ENOMEM);
-
- OBD_ALLOC(ioarr, sizeof(*ioarr) * oa_bufs);
- if (!ioarr)
- GOTO(out_where, rc = -ENOMEM);
-
- for (i = 0; i < oa_bufs; i++) {
- where[i] = lov_stripe_number(lsm, pga[i].off);
- stripeinfo[where[i]].bufct++;
- }
-
- for (i = 0, loi = lsm->lsm_oinfo, si_last = si = stripeinfo;
- i < stripe_count; i++, loi++, si_last = si, si++) {
- if (lov->tgts[loi->loi_ost_idx].active == 0)
- GOTO(out_ioarr, rc = -EIO);
- if (i > 0)
- si->index = si_last->index + si_last->bufct;
- si->lsm.lsm_object_id = loi->loi_id;
- si->ost_idx = loi->loi_ost_idx;
- }
-
- for (i = 0; i < oa_bufs; i++) {
- int which = where[i];
- int shift;
-
- shift = stripeinfo[which].index + stripeinfo[which].subcount;
- LASSERT(shift < oa_bufs);
- ioarr[shift] = pga[i];
- ioarr[shift].off = lov_stripe_offset(lsm, pga[i].off, which);
- stripeinfo[which].subcount++;
- }
-
- for (i = 0, si = stripeinfo; i < stripe_count; i++, si++) {
- int shift = si->index;
-
- if (si->bufct) {
- LASSERT(shift < oa_bufs);
- rc = obd_brw(cmd, &lov->tgts[si->ost_idx].conn,
- &si->lsm, si->bufct, &ioarr[shift], set);
- if (rc)
- GOTO(out_ioarr, rc);
- }
- }
-
- out_ioarr:
- OBD_FREE(ioarr, sizeof(*ioarr) * oa_bufs);
- out_where:
- OBD_FREE(where, sizeof(*where) * oa_bufs);
- out_sinfo:
- OBD_FREE(stripeinfo, stripe_count * sizeof(*stripeinfo));
- out_cbdata:
- RETURN(rc);
-}
-
-static int lov_enqueue(struct lustre_handle *conn, struct lov_stripe_md *lsm,
- struct lustre_handle *parent_lock,
- __u32 type, void *cookie, int cookielen, __u32 mode,
- int *flags, void *cb, void *data, int datalen,
- struct lustre_handle *lockhs)
-{
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct lov_oinfo *loi;
- struct lov_stripe_md submd;
- int rc = 0, i;
- ENTRY;
-
- if (!lsm) {
- CERROR("LOV requires striping ea\n");
- RETURN(-EINVAL);
- }
-
- if (lsm->lsm_magic != LOV_MAGIC) {
- CERROR("LOV striping magic bad %#lx != %#lx\n",
- lsm->lsm_magic, LOV_MAGIC);
- RETURN(-EINVAL);
- }
-
- /* we should never be asked to replay a lock. */
-
- LASSERT((*flags & LDLM_FL_REPLAY) == 0);
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- memset(lockhs, 0, sizeof(*lockhs) * lsm->lsm_stripe_count);
-
- lov = &export->exp_obd->u.lov;
- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
- struct ldlm_extent *extent = (struct ldlm_extent *)cookie;
- struct ldlm_extent sub_ext;
-
- if (lov->tgts[loi->loi_ost_idx].active == 0)
- continue;
-
- *flags = 0;
- sub_ext.start = lov_stripe_offset(lsm, extent->start, i);
- sub_ext.end = lov_stripe_offset(lsm, extent->end, i);
- if (sub_ext.start == sub_ext.end)
- continue;
-
- submd.lsm_object_id = loi->loi_id;
- /* XXX submd should be that from the subobj, it should come
- * opaquely from the LOV.
- */
- submd.lsm_stripe_count = 0;
- /* XXX submd is not fully initialized here */
- *flags = 0;
- rc = obd_enqueue(&(lov->tgts[loi->loi_ost_idx].conn), &submd,
- parent_lock, type, &sub_ext, sizeof(sub_ext),
- mode, flags, cb, data, datalen, &(lockhs[i]));
- // XXX add a lock debug statement here
- if (rc && lov->tgts[loi->loi_ost_idx].active) {
- CERROR("Error enqueue objid "LPX64" subobj "LPX64
- " on OST idx %d: rc = %d\n", lsm->lsm_object_id,
- loi->loi_id, loi->loi_ost_idx, rc);
- goto out_locks;
- }
- }
-
- RETURN(0);
-
- out_locks:
- for (i--, loi = &lsm->lsm_oinfo[i]; i >= 0; i--, loi--) {
- int err;
-
- if (lov->tgts[loi->loi_ost_idx].active == 0)
- continue;
-
- submd.lsm_object_id = loi->loi_id;
- submd.lsm_stripe_count = 0;
- err = obd_cancel(&lov->tgts[loi->loi_ost_idx].conn, &submd,
- mode, &lockhs[i]);
- if (err) {
- CERROR("Error cancelling objid "LPX64" subobj "LPX64
- " on OST idx %d after enqueue error: rc = %d\n",
- loi->loi_id, loi->loi_ost_idx, err);
- }
- }
- RETURN(rc);
-}
-
-static int lov_cancel(struct lustre_handle *conn, struct lov_stripe_md *lsm,
- __u32 mode, struct lustre_handle *lockhs)
-{
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct lov_oinfo *loi;
- int rc = 0, i;
- ENTRY;
-
- if (!lsm) {
- CERROR("LOV requires striping ea\n");
- RETURN(-EINVAL);
- }
-
- if (lsm->lsm_magic != LOV_MAGIC) {
- CERROR("LOV striping magic bad %#lx != %#lx\n",
- lsm->lsm_magic, LOV_MAGIC);
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- lov = &export->exp_obd->u.lov;
- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
- struct lov_stripe_md submd;
- int err;
-
- if (lov->tgts[loi->loi_ost_idx].active == 0)
- continue;
-
- if (lockhs[i].addr == 0)
- continue;
-
- submd.lsm_object_id = loi->loi_id;
- submd.lsm_stripe_count = 0;
- err = obd_cancel(&lov->tgts[loi->loi_ost_idx].conn, &submd,
- mode, &lockhs[i]);
- if (err && lov->tgts[loi->loi_ost_idx].active) {
- CERROR("Error cancel objid "LPX64" subobj "LPX64
- " on OST idx %d: rc = %d\n", lsm->lsm_object_id,
- loi->loi_id, loi->loi_ost_idx, err);
- if (!rc)
- rc = err;
- }
- }
- RETURN(rc);
-}
-
-static int lov_cancel_unused(struct lustre_handle *conn,
- struct lov_stripe_md *lsm, int flags)
-{
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct lov_oinfo *loi;
- int rc = 0, i, err;
- ENTRY;
-
- if (!lsm) {
- CERROR("LOV requires striping ea for lock cancellation\n");
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- lov = &export->exp_obd->u.lov;
- for (i = 0,loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++,loi++) {
- struct lov_stripe_md submd;
-
- submd.lsm_object_id = loi->loi_id;
- submd.lsm_stripe_count = 0;
- err = obd_cancel_unused(&lov->tgts[loi->loi_ost_idx].conn,
- &submd, flags);
- if (err && lov->tgts[loi->loi_ost_idx].active) {
- CERROR("Error cancel unused objid "LPX64" subobj "LPX64
- " on OST idx %d: rc = %d\n", lsm->lsm_object_id,
- loi->loi_id, loi->loi_ost_idx, err);
- if (!rc)
- rc = err;
- }
- }
-
- RETURN(rc);
-}
-
-static int lov_statfs(struct lustre_handle *conn, struct obd_statfs *osfs)
-{
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct obd_statfs lov_sfs;
- int set = 0;
- int rc = 0;
- int i;
- ENTRY;
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- lov = &export->exp_obd->u.lov;
-
- /* We only get block data from the OBD */
- for (i = 0; i < lov->desc.ld_tgt_count; i++) {
- int err;
-
- if (!lov->tgts[i].active)
- continue;
-
- err = obd_statfs(&lov->tgts[i].conn, &lov_sfs);
- if (err) {
- CERROR("Error statfs OSC %s idx %d: err = %d\n",
- lov->tgts[i].uuid, i, err);
- if (!rc)
- rc = err;
- continue; /* XXX or break? - probably OK to continue */
- }
- if (!set) {
- memcpy(osfs, &lov_sfs, sizeof(lov_sfs));
- set = 1;
- } else {
- osfs->os_bfree += lov_sfs.os_bfree;
- osfs->os_bavail += lov_sfs.os_bavail;
- osfs->os_blocks += lov_sfs.os_blocks;
- /* XXX not sure about this one - depends on policy.
- * - could be minimum if we always stripe on all OBDs
- * (but that would be wrong for any other policy,
- * if one of the OBDs has no more objects left)
- * - could be sum if we stripe whole objects
- * - could be average, just to give a nice number
- * - we just pick first OST and hope it is enough
- sfs->f_ffree += lov_sfs.f_ffree;
- */
- }
- }
- RETURN(rc);
-}
-
-static int lov_iocontrol(unsigned int cmd, struct lustre_handle *conn, int len,
- void *karg, void *uarg)
-{
- struct obd_device *obddev = class_conn2obd(conn);
- struct lov_obd *lov = &obddev->u.lov;
- struct obd_ioctl_data *data = karg;
- int i, count = lov->desc.ld_tgt_count;
- int rc;
-
- ENTRY;
-
- switch (cmd) {
- case IOC_LOV_SET_OSC_ACTIVE: {
- rc = lov_set_osc_active(lov,data->ioc_inlbuf1,data->ioc_offset);
- break;
- }
- case OBD_IOC_LOV_GET_CONFIG: {
- struct lov_tgt_desc *tgtdesc;
- struct lov_desc *desc;
- obd_uuid_t *uuidp;
- char *buf = NULL;
-
- buf = NULL;
- len = 0;
- if (obd_ioctl_getdata(&buf, &len, (void *)uarg))
- RETURN(-EINVAL);
-
- data = (struct obd_ioctl_data *)buf;
-
- if (sizeof(*desc) > data->ioc_inllen1) {
- OBD_FREE(buf, len);
- RETURN(-EINVAL);
- }
-
- if (sizeof(*uuidp) * count > data->ioc_inllen2) {
- OBD_FREE(buf, len);
- RETURN(-EINVAL);
- }
-
- desc = (struct lov_desc *)data->ioc_inlbuf1;
- uuidp = (obd_uuid_t *)data->ioc_inlbuf2;
- memcpy(desc, &(lov->desc), sizeof(*desc));
-
- tgtdesc = lov->tgts;
- for (i = 0; i < count; i++, uuidp++, tgtdesc++)
- memcpy(uuidp, tgtdesc->uuid, sizeof(*uuidp));
-
- rc = copy_to_user((void *)uarg, buf, len);
- if (rc)
- rc = -EFAULT;
- OBD_FREE(buf, len);
- break;
- }
- default:
- if (count == 0)
- RETURN(-ENOTTY);
- rc = 0;
- for (i = 0; i < count; i++) {
- int err = obd_iocontrol(cmd, &lov->tgts[i].conn,
- len, karg, uarg);
- if (err && !rc)
- rc = err;
- }
- }
-
- RETURN(rc);
-}
-
-struct obd_ops lov_obd_ops = {
- o_attach: lov_attach,
- o_detach: lov_detach,
- o_setup: lov_setup,
- o_connect: lov_connect,
- o_disconnect: lov_disconnect,
- o_statfs: lov_statfs,
- o_packmd: lov_packmd,
- o_unpackmd: lov_unpackmd,
- o_create: lov_create,
- o_destroy: lov_destroy,
- o_getattr: lov_getattr,
- o_setattr: lov_setattr,
- o_open: lov_open,
- o_close: lov_close,
- o_brw: lov_brw,
- o_punch: lov_punch,
- o_enqueue: lov_enqueue,
- o_cancel: lov_cancel,
- o_cancel_unused: lov_cancel_unused,
- o_iocontrol: lov_iocontrol
-};
-
-
-#define LOV_VERSION "v0.1"
-
-static int __init lov_init(void)
-{
- int rc;
- printk(KERN_INFO "Lustre Logical Object Volume driver " LOV_VERSION
- ", info@clusterfs.com\n");
- lov_file_cache = kmem_cache_create("ll_lov_file_data",
- sizeof(struct lov_file_handles),
- 0, 0, NULL, NULL);
- if (!lov_file_cache)
- RETURN(-ENOMEM);
-
- rc = class_register_type(&lov_obd_ops, status_class_var,
- OBD_LOV_DEVICENAME);
- RETURN(rc);
-}
-
-static void __exit lov_exit(void)
-{
- if (kmem_cache_destroy(lov_file_cache))
- CERROR("couldn't free LOV open cache\n");
- class_unregister_type(OBD_LOV_DEVICENAME);
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Logical Object Volume OBD driver " LOV_VERSION);
-MODULE_LICENSE("GPL");
-
-module_init(lov_init);
-module_exit(lov_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc. <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * (Un)packing of OST/MDS requests
- *
- */
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_net.h>
-#include <linux/obd.h>
-#include <linux/obd_lov.h>
-#include <linux/obd_support.h>
-
-/* lov_packdesc() is in mds/mds_lov.c */
-
-void lov_unpackdesc(struct lov_desc *ld)
-{
- ld->ld_tgt_count = NTOH__u32(ld->ld_tgt_count);
- ld->ld_default_stripe_count = HTON__u32(ld->ld_default_stripe_count);
- ld->ld_default_stripe_size = HTON__u32(ld->ld_default_stripe_size);
- ld->ld_pattern = HTON__u32(ld->ld_pattern);
-}
-
-/* Pack LOV object metadata for shipment to the MDS.
- *
- * XXX In the future, this will be enhanced to get the EA size from the
- * underlying OSC device(s) to get their EA sizes so we can stack
- * LOVs properly. For now lov_mds_md_size() just assumes one obd_id
- * per stripe.
- */
-int lov_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp,
- struct lov_stripe_md *lsm)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct lov_obd *lov = &obd->u.lov;
- struct lov_oinfo *loi;
- struct lov_mds_md *lmm;
- int ost_count = lov->desc.ld_tgt_count;
- int stripe_count = ost_count;
- int lmm_size;
- int i;
- ENTRY;
-
- if (lsm)
- stripe_count = lsm->lsm_stripe_count;
-
- /* XXX LOV STACKING call into osc for sizes */
- lmm_size = lov_mds_md_size(ost_count);
-
- if (!lmmp)
- RETURN(lmm_size);
-
- if (*lmmp && !lsm) {
- /* endianness */
- ost_count = ((*lmmp)->lmm_ost_count);
- OBD_FREE(*lmmp, lov_mds_md_size(ost_count));
- *lmmp = NULL;
- RETURN(0);
- }
-
- if (!*lmmp) {
- OBD_ALLOC(*lmmp, lmm_size);
- if (!*lmmp)
- RETURN(-ENOMEM);
- }
-
- lmm = *lmmp;
-
- lmm->lmm_stripe_count = (stripe_count);
- if (!lsm)
- RETURN(lmm_size);
- /* XXX endianness */
- lmm->lmm_magic = (lsm->lsm_magic);
- lmm->lmm_object_id = (lsm->lsm_object_id);
- lmm->lmm_stripe_size = (lsm->lsm_stripe_size);
- lmm->lmm_stripe_pattern = (lsm->lsm_stripe_pattern);
- lmm->lmm_stripe_offset = (lsm->lsm_stripe_offset);
- lmm->lmm_ost_count = (lov->desc.ld_tgt_count);
-
- /* Only fill in the object ids which we are actually using.
- * Assumes lmm_objects is otherwise zero-filled. */
- for (i = 0, loi = lsm->lsm_oinfo; i < stripe_count; i++, loi++)
- /* XXX call down to osc_packmd() to do the packing */
- lmm->lmm_objects[loi->loi_ost_idx].l_object_id = (loi->loi_id);
-
- RETURN(lmm_size);
-}
-
-int lov_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
- struct lov_mds_md *lmm)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct lov_obd *lov = &obd->u.lov;
- struct lov_stripe_md *lsm;
- struct lov_oinfo *loi;
- int ost_count = lov->desc.ld_active_tgt_count;
- int ost_offset = 0;
- int stripe_count = 0;
- int lsm_size;
- int i;
- ENTRY;
-
- if (lmm)
- /* endianness */
- stripe_count = (lmm->lmm_stripe_count);
-
- if (!stripe_count)
- stripe_count = lov->desc.ld_default_stripe_count;
- if (!stripe_count || stripe_count > ost_count)
- stripe_count = ost_count;
-
- /* XXX LOV STACKING call into osc for sizes */
- lsm_size = lov_stripe_md_size(stripe_count);
-
- if (!lsmp)
- RETURN(lsm_size);
-
- if (*lsmp && !lmm) {
- stripe_count = (*lsmp)->lsm_stripe_count;
- OBD_FREE(*lsmp, lov_stripe_md_size(stripe_count));
- *lsmp = NULL;
- RETURN(0);
- }
-
- if (!*lsmp) {
- OBD_ALLOC(*lsmp, lsm_size);
- if (!*lsmp)
- RETURN(-ENOMEM);
- }
-
- lsm = *lsmp;
-
- lsm->lsm_stripe_count = stripe_count;
- if (!lmm)
- RETURN(lsm_size);
-
- /* XXX endianness */
- ost_offset = lsm->lsm_stripe_offset = (lmm->lmm_stripe_offset);
- lsm->lsm_magic = (lmm->lmm_magic);
- lsm->lsm_object_id = (lmm->lmm_object_id);
- lsm->lsm_stripe_size = (lmm->lmm_stripe_size);
- lsm->lsm_stripe_pattern = (lmm->lmm_stripe_pattern);
-
- for (i = 0, loi = lsm->lsm_oinfo; i < ost_count; i++, ost_offset++) {
- ost_offset %= ost_count;
-
- if (!lmm->lmm_objects[ost_offset].l_object_id)
- continue;
-
- LASSERT(loi - lsm->lsm_oinfo < stripe_count);
- /* XXX LOV STACKING call down to osc_unpackmd() */
- loi->loi_id = (lmm->lmm_objects[ost_offset].l_object_id);
- loi->loi_ost_idx = ost_offset;
- loi++;
- }
-
- RETURN(lsm_size);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-/*
- * Common STATUS namespace
- */
-
-int rd_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct obd_device* dev = (struct obd_device*)data;
- len += snprintf(page, count, "%s\n", dev->obd_uuid);
- return len;
-
-
-}
-int rd_stripesize(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* dev = (struct obd_device*)data;
- int len = 0;
- struct lov_obd* lov = &dev->u.lov;
- len += snprintf(page, count, LPU64"\n",
- (__u64)(lov->desc.ld_default_stripe_size));
-
- return len;
-}
-
-int rd_stripeoffset(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* dev = (struct obd_device*)data;
- int len = 0;
- struct lov_obd* lov = &dev->u.lov;
- len += snprintf(page, count, LPU64"\n",
- lov->desc.ld_default_stripe_offset);
- return len;
-
-}
-
-int rd_stripetype(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* dev = (struct obd_device*)data;
- int len = 0;
- struct lov_obd* lov = &dev->u.lov;
- len += snprintf(page, count, LPU64"\n",
- (__u64)(lov->desc.ld_pattern));
- return len;
-
-}
-int rd_stripecount(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* dev = (struct obd_device*)data;
- int len = 0;
- struct lov_obd* lov = &dev->u.lov;
- len += snprintf(page, count, LPU64"\n",
- (__u64)(lov->desc.ld_default_stripe_count));
- return len;
-
-}
-int rd_numobd(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* dev = (struct obd_device*)data;
- int len = 0;
- struct lov_obd* lov=&dev->u.lov;
- len += snprintf(page, count, LPU64"\n",
- (__u64)(lov->desc.ld_tgt_count));
- return len;
-
-}
-
-int rd_activeobd(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* dev = (struct obd_device*)data;
- int len = 0;
- struct lov_obd* lov = &dev->u.lov;
- len += snprintf(page, count, LPU64"\n",
- (__u64)(lov->desc.ld_active_tgt_count));
- return len;
-
-}
-
-int rd_blksize(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-
-int rd_kbtotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-
-int rd_kbfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_filestotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_filesfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_filegroups(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_target(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* dev = (struct obd_device*)data;
- int len = 0, i = 0;
- struct lov_obd* lov = &dev->u.lov;
- struct lov_tgt_desc* tgts = lov->tgts;
- while(i < lov->desc.ld_tgt_count){
- len += snprintf(&page[len], count, "%d: %s\n", i, tgts->uuid);
- i++;
- tgts++;
- }
-
- return len;
-}
-int rd_mdc(char* page, char **start, off_t off, int count, int *eof, void *data)
-{
- struct obd_device* dev = (struct obd_device*)data;
- int len = 0;
- struct lov_obd* lov = &dev->u.lov;
- len += snprintf(page, count, "%s\n", lov->mdcobd->obd_uuid);
- return len;
-}
-
-struct lprocfs_vars status_var_nm_1[] = {
- {"status/uuid", rd_uuid, 0, 0},
- {"status/stripesize",rd_stripesize, 0, 0},
- {"status/stripeoffset",rd_stripeoffset, 0, 0},
- {"status/stripecount",rd_stripecount, 0, 0},
- {"status/stripetype", rd_stripetype, 0, 0},
- {"status/numobd",rd_numobd, 0, 0},
- {"status/activeobd", rd_activeobd, 0, 0},
- {"status/filestotal", rd_filestotal, 0, 0},
- {"status/filesfree", rd_filesfree, 0, 0},
- {"status/filegroups", rd_filegroups, 0, 0},
- {"status/blocksize", rd_blksize, 0, 0},
- {"status/kbytestotal", rd_kbtotal, 0, 0},
- {"status/kbytesfree", rd_kbfree, 0, 0},
- {"status/target_obd", rd_target, 0, 0},
- {"status/target_mdc", rd_mdc, 0, 0},
-
- {0}
-};
-int rd_numrefs(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_type* class = (struct obd_type*)data;
- int len = 0;
- len += snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-struct lprocfs_vars status_class_var[]={
- {"status/num_refs", rd_numrefs, 0, 0},
- {0}
-};
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=
-
-MODULE = mdc
-modulefs_DATA = mdc.o
-EXTRA_PROGRAMS = mdc
-
-LINX= mds_updates.c ll_pack.c client.c
-mdc_SOURCES = mdc_request.c mdc_reint.c lproc_mdc.c $(LINX)
-
-ll_pack.c:
- test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c .
-mds_updates.c:
- test -e mds_updates.c || ln -sf $(top_srcdir)/lib/mds_updates.c .
-client.c:
- test -e client.c || ln -sf $(top_srcdir)/lib/client.c .
-
-include $(top_srcdir)/Rules
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-
-int rd_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
-
- struct obd_device* temp = (struct obd_device*)data;
- int len = 0;
- len += snprintf(page, count, "%s\n",temp->obd_uuid);
- return len;
-
-
-}
-int rd_blksize(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-int rd_kbtotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_kbfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-
-int rd_filestotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_filesfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_filegroups(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-int rd_conn_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct client_obd* cli = &temp->u.cli;
- struct obd_import* imp = &cli->cl_import;
- int len = 0;
-
- len += snprintf(page, count, "%s\n",imp->imp_connection->c_remote_uuid);
- return len;
-}
-
-int rd_server_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct client_obd* cli = &temp->u.cli;
- int len = 0;
-
- len += snprintf(page, count, "%s\n",cli->cl_target_uuid);
- return len;
-}
-
-int rd_server_name(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-
-}
-
-struct lprocfs_vars status_var_nm_1[] = {
- {"status/uuid", rd_uuid, 0, 0},
- {"status/blocksize",rd_blksize, 0, 0},
- {"status/kbytestotal",rd_kbtotal, 0, 0},
- {"status/kbytesfree", rd_kbfree, 0, 0},
- {"status/filestotal", rd_filestotal, 0, 0},
- {"status/filesfree", rd_filesfree, 0, 0},
- {"status/filegroups", rd_filegroups, 0, 0},
- {"status/mds_server_uuid", rd_server_uuid, 0, 0},
- {"status/mds_conn_uuid", rd_conn_uuid, 0, 0},
- {0}
-};
-int rd_numrefs(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_type* class = (struct obd_type*)data;
- int len = 0;
- len += snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-struct lprocfs_vars status_class_var[] = {
- {"status/num_refs", rd_numrefs, 0, 0},
- {0}
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.sf.net/projects/lustre/
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define EXPORT_SYMTAB
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-#define DEBUG_SUBSYSTEM S_MDC
-
-#include <linux/obd_class.h>
-#include <linux/lustre_mds.h>
-
-static int mdc_reint(struct ptlrpc_request *request, int level)
-{
- int rc;
- request->rq_level = level;
-
- rc = ptlrpc_queue_wait(request);
-
- if (rc) {
- CERROR("error in handling %d\n", rc);
- } else {
- /* For future resend/replays. */
- u32 *opcodeptr = lustre_msg_buf(request->rq_reqmsg, 0);
- *opcodeptr |= REINT_REPLAYING;
- }
- return rc;
-}
-
-int mdc_setattr(struct lustre_handle *conn,
- struct inode *inode, struct iattr *iattr,
- struct ptlrpc_request **request)
-{
- struct ptlrpc_request *req;
- struct mds_rec_setattr *rec;
- int rc, size = sizeof(*rec);
- ENTRY;
-
- req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_REINT, 1, &size,
- NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- mds_setattr_pack(req, 0, inode, iattr, NULL, 0);
-
- size = sizeof(struct mds_body);
- req->rq_replen = lustre_msg_size(1, &size);
-
- rc = mdc_reint(req, LUSTRE_CONN_FULL);
- *request = req;
- if (rc == -ERESTARTSYS )
- rc = 0;
-
- RETURN(rc);
-}
-
-int mdc_create(struct lustre_handle *conn, struct inode *dir,
- const char *name, int namelen, const void *data, int datalen,
- int mode, __u32 uid, __u32 gid, __u64 time, __u64 rdev,
- struct ptlrpc_request **request)
-{
- struct ptlrpc_request *req;
- int rc, size[3] = {sizeof(struct mds_rec_create), namelen + 1, 0};
- int level, bufcount = 2;
- ENTRY;
-
- if (data && datalen) {
- size[bufcount] = datalen;
- bufcount++;
- }
-
- req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_REINT, bufcount,
- size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- /* mds_create_pack fills msg->bufs[1] with name
- * and msg->bufs[2] with tgt, for symlinks or lov MD data */
- mds_create_pack(req, 0, dir, mode, rdev, uid, gid, time,
- name, namelen, data, datalen);
-
- size[0] = sizeof(struct mds_body);
- req->rq_replen = lustre_msg_size(1, size);
-
- level = LUSTRE_CONN_FULL;
- resend:
- rc = mdc_reint(req, level);
- /* Resend if we were told to. */
- if (rc == -ERESTARTSYS) {
- level = LUSTRE_CONN_RECOVD;
- req->rq_flags = 0;
- goto resend;
- }
-
- mdc_store_inode_generation(req, 0, 0);
-
- *request = req;
- RETURN(rc);
-}
-
-int mdc_unlink(struct lustre_handle *conn, struct inode *dir,
- struct inode *child, __u32 mode, const char *name, int namelen,
- struct ptlrpc_request **request)
-{
- struct ptlrpc_request *req;
- int rc, size[2] = {sizeof(struct mds_rec_unlink), namelen + 1};
- ENTRY;
-
- req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_REINT, 2, size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- mds_unlink_pack(req, 0, dir, child, mode, name, namelen);
-
- size[0] = sizeof(struct mds_body);
- req->rq_replen = lustre_msg_size(1, size);
-
- rc = mdc_reint(req, LUSTRE_CONN_FULL);
- *request = req;
- if (rc == -ERESTARTSYS)
- rc = 0;
-
- RETURN(rc);
-}
-
-int mdc_link(struct lustre_handle *conn,
- struct dentry *src, struct inode *dir, const char *name,
- int namelen, struct ptlrpc_request **request)
-{
- struct ptlrpc_request *req;
- int rc, size[2] = {sizeof(struct mds_rec_link), namelen + 1};
- ENTRY;
-
- req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_REINT, 2, size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- mds_link_pack(req, 0, src->d_inode, dir, name, namelen);
-
- size[0] = sizeof(struct mds_body);
- req->rq_replen = lustre_msg_size(1, size);
-
- rc = mdc_reint(req, LUSTRE_CONN_FULL);
- *request = req;
- if (rc == -ERESTARTSYS )
- rc = 0;
-
- RETURN(rc);
-}
-
-int mdc_rename(struct lustre_handle *conn,
- struct inode *src, struct inode *tgt, const char *old,
- int oldlen, const char *new, int newlen,
- struct ptlrpc_request **request)
-{
- struct ptlrpc_request *req;
- int rc, size[3] = {sizeof(struct mds_rec_rename), oldlen + 1,
- newlen + 1};
- ENTRY;
-
- req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_REINT, 3, size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- mds_rename_pack(req, 0, src, tgt, old, oldlen, new, newlen);
-
- size[0] = sizeof(struct mds_body);
- req->rq_replen = lustre_msg_size(1, size);
-
- rc = mdc_reint(req, LUSTRE_CONN_FULL);
- *request = req;
- if (rc == -ERESTARTSYS)
- rc = 0;
-
- RETURN(rc);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.sf.net/projects/lustre/
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_MDC
-
-#include <linux/module.h>
-#include <linux/miscdevice.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_lite.h>
-#include <linux/lustre_dlm.h>
-#include <linux/init.h>
-#include <linux/lprocfs_status.h>
-
-#define REQUEST_MINOR 244
-
-extern int mds_queue_req(struct ptlrpc_request *);
-extern struct lprocfs_vars status_var_nm_1[];
-extern struct lprocfs_vars status_class_var[];
-
-/* should become mdc_getinfo() */
-int mdc_getstatus(struct lustre_handle *conn, struct ll_fid *rootfid)
-{
- struct ptlrpc_request *req;
- struct mds_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_GETSTATUS, 1, &size,
- NULL);
- if (!req)
- GOTO(out, rc = -ENOMEM);
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- req->rq_level = LUSTRE_CONN_CON;
- req->rq_replen = lustre_msg_size(1, &size);
-
- mds_pack_req_body(req);
- rc = ptlrpc_queue_wait(req);
-
- if (!rc) {
- body = lustre_msg_buf(req->rq_repmsg, 0);
- mds_unpack_body(body);
- memcpy(rootfid, &body->fid1, sizeof(*rootfid));
-
- CDEBUG(D_NET, "root ino="LPU64", last_committed="LPU64
- ", last_xid="LPU64"\n",
- rootfid->id, req->rq_repmsg->last_committed,
- req->rq_repmsg->last_xid);
- }
-
- EXIT;
- out:
- ptlrpc_req_finished(req);
- return rc;
-}
-
-int mdc_getlovinfo(struct obd_device *obd, struct lustre_handle *mdc_connh,
- struct ptlrpc_request **request)
-{
- struct ptlrpc_request *req;
- struct mds_status_req *streq;
- int rc, size[2] = {sizeof(*streq)};
- ENTRY;
-
- req = ptlrpc_prep_req(class_conn2cliimp(mdc_connh), MDS_GETLOVINFO, 1,
- size, NULL);
- if (!req)
- GOTO(out, rc = -ENOMEM);
-
- *request = req;
- streq = lustre_msg_buf(req->rq_reqmsg, 0);
- streq->flags = HTON__u32(MDS_STATUS_LOV);
- streq->repbuf = HTON__u32(8192);
-
- /* prepare for reply */
- req->rq_level = LUSTRE_CONN_CON;
- size[0] = 512;
- size[1] = 8192;
- req->rq_replen = lustre_msg_size(2, size);
-
- rc = ptlrpc_queue_wait(req);
-
- out:
- RETURN(rc);
-}
-
-
-int mdc_getattr(struct lustre_handle *conn,
- obd_id ino, int type, unsigned long valid, size_t ea_size,
- struct ptlrpc_request **request)
-{
- struct ptlrpc_request *req;
- struct mds_body *body;
- int rc, size[2] = {sizeof(*body), 0}, bufcount = 1;
- ENTRY;
-
- /* XXX do we need to make another request here? We just did a getattr
- * to do the lookup in the first place.
- */
- req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_GETATTR, 1, size,
- NULL);
- if (!req)
- GOTO(out, rc = -ENOMEM);
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- ll_ino2fid(&body->fid1, ino, 0, type);
- body->valid = valid;
-
- if (ea_size) {
- size[bufcount] = ea_size;
- bufcount++;
- body->size = ea_size;
- CDEBUG(D_INODE, "reserving %d bytes for MD/symlink in packet\n",
- ea_size);
- }
- req->rq_replen = lustre_msg_size(bufcount, size);
- mds_pack_req_body(req);
-
- rc = ptlrpc_queue_wait(req);
-
- if (!rc) {
- body = lustre_msg_buf(req->rq_repmsg, 0);
- mds_unpack_body(body);
- CDEBUG(D_NET, "mode: %o\n", body->mode);
- }
-
- EXIT;
- out:
- *request = req;
- return rc;
-}
-
-void d_delete_aliases(struct inode *inode)
-{
- struct dentry *dentry = NULL;
- struct list_head *tmp;
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- ENTRY;
-
- spin_lock(&dcache_lock);
- list_for_each(tmp, &inode->i_dentry) {
- dentry = list_entry(tmp, struct dentry, d_alias);
-
- list_del_init(&dentry->d_hash);
- list_add(&dentry->d_hash, &sbi->ll_orphan_dentry_list);
- }
-
- spin_unlock(&dcache_lock);
- EXIT;
-}
-
-static int mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
- void *data, __u32 data_len, int flag)
-{
- int rc;
- struct lustre_handle lockh;
- ENTRY;
-
- switch (flag) {
- case LDLM_CB_BLOCKING:
- ldlm_lock2handle(lock, &lockh);
- rc = ldlm_cli_cancel(&lockh);
- if (rc < 0) {
- CDEBUG(D_INODE, "ldlm_cli_cancel: %d\n", rc);
- RETURN(rc);
- }
- break;
- case LDLM_CB_CANCELING: {
- /* Invalidate all dentries associated with this inode */
- struct inode *inode = data;
-
-#warning "FIXME: what tells us that 'inode' is valid at all?"
- if (inode->i_state & I_FREEING)
- break;
-
- LASSERT(inode != NULL);
- LASSERT(data_len == sizeof(*inode));
-
- if (S_ISDIR(inode->i_mode)) {
- CDEBUG(D_INODE, "invalidating inode %ld\n",
- inode->i_ino);
-
- ll_invalidate_inode_pages(inode);
- }
-
- if ( inode != inode->i_sb->s_root->d_inode ) {
- /* XXX should this igrab move up 12 lines? */
- LASSERT(igrab(inode) == inode);
- d_delete_aliases(inode);
- iput(inode);
- }
- break;
- }
- default:
- LBUG();
- }
-
- RETURN(0);
-}
-
-/* This should be called with both the request and the reply still packed. */
-void mdc_store_inode_generation(struct ptlrpc_request *req, int reqoff,
- int repoff)
-{
- struct mds_rec_create *rec = lustre_msg_buf(req->rq_reqmsg, reqoff);
- struct mds_body *body = lustre_msg_buf(req->rq_repmsg, repoff);
-
- DEBUG_REQ(D_HA, req, "storing generation %x for ino "LPD64,
- body->fid1.generation, body->fid1.id);
- memcpy(&rec->cr_replayfid, &body->fid1, sizeof rec->cr_replayfid);
-}
-
-int mdc_enqueue(struct lustre_handle *conn, int lock_type,
- struct lookup_intent *it, int lock_mode, struct inode *dir,
- struct dentry *de, struct lustre_handle *lockh,
- char *tgt, int tgtlen, void *data, int datalen)
-{
- struct ptlrpc_request *req;
- struct obd_device *obddev = class_conn2obd(conn);
- __u64 res_id[RES_NAME_SIZE] = {dir->i_ino, (__u64)dir->i_generation};
- int size[6] = {sizeof(struct ldlm_request), sizeof(struct ldlm_intent)};
- int rc, flags = LDLM_FL_HAS_INTENT;
- int repsize[3] = {sizeof(struct ldlm_reply),
- sizeof(struct mds_body),
- obddev->u.cli.cl_max_mds_easize};
- struct ldlm_reply *dlm_rep;
- struct ldlm_intent *lit;
- struct ldlm_request *lockreq;
- ENTRY;
-
- LDLM_DEBUG_NOLOCK("mdsintent %s parent dir %ld",
- ldlm_it2str(it->it_op), dir->i_ino);
-
- if (it->it_op & (IT_MKDIR | IT_CREAT | IT_SYMLINK | IT_MKNOD)) {
- switch (it->it_op) {
- case IT_MKDIR:
- it->it_mode |= S_IFDIR;
- break;
- case (IT_CREAT|IT_OPEN):
- case IT_CREAT:
- it->it_mode |= S_IFREG;
- break;
- case IT_SYMLINK:
- it->it_mode |= S_IFLNK;
- break;
- }
- it->it_mode &= ~current->fs->umask;
-
- size[2] = sizeof(struct mds_rec_create);
- size[3] = de->d_name.len + 1;
- size[4] = tgtlen + 1;
- req = ptlrpc_prep_req(class_conn2cliimp(conn), LDLM_ENQUEUE, 5,
- size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- /* pack the intent */
- lit = lustre_msg_buf(req->rq_reqmsg, 1);
- lit->opc = NTOH__u64((__u64)it->it_op);
-
- /* pack the intended request */
- mds_create_pack(req, 2, dir, it->it_mode, 0, current->fsuid,
- current->fsgid, CURRENT_TIME, de->d_name.name,
- de->d_name.len, tgt, tgtlen);
- req->rq_replen = lustre_msg_size(3, repsize);
- } else if (it->it_op == IT_RENAME2) {
- struct dentry *old_de = it->it_data;
-
- size[2] = sizeof(struct mds_rec_rename);
- size[3] = old_de->d_name.len + 1;
- size[4] = de->d_name.len + 1;
- req = ptlrpc_prep_req(class_conn2cliimp(conn), LDLM_ENQUEUE, 5,
- size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- /* pack the intent */
- lit = lustre_msg_buf(req->rq_reqmsg, 1);
- lit->opc = NTOH__u64((__u64)it->it_op);
-
- /* pack the intended request */
- mds_rename_pack(req, 2, old_de->d_parent->d_inode, dir,
- old_de->d_name.name, old_de->d_name.len,
- de->d_name.name, de->d_name.len);
- req->rq_replen = lustre_msg_size(3, repsize);
- } else if (it->it_op == IT_LINK2) {
- struct dentry *old_de = it->it_data;
-
- size[2] = sizeof(struct mds_rec_link);
- size[3] = de->d_name.len + 1;
- req = ptlrpc_prep_req(class_conn2cliimp(conn), LDLM_ENQUEUE, 4,
- size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- /* pack the intent */
- lit = lustre_msg_buf(req->rq_reqmsg, 1);
- lit->opc = NTOH__u64((__u64)it->it_op);
-
- /* pack the intended request */
- mds_link_pack(req, 2, old_de->d_inode, dir,
- de->d_name.name, de->d_name.len);
- req->rq_replen = lustre_msg_size(3, repsize);
- } else if (it->it_op == IT_UNLINK || it->it_op == IT_RMDIR) {
- size[2] = sizeof(struct mds_rec_unlink);
- size[3] = de->d_name.len + 1;
- req = ptlrpc_prep_req(class_conn2cliimp(conn), LDLM_ENQUEUE, 4,
- size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- /* pack the intent */
- lit = lustre_msg_buf(req->rq_reqmsg, 1);
- lit->opc = NTOH__u64((__u64)it->it_op);
-
- /* pack the intended request */
- mds_unlink_pack(req, 2, dir, NULL,
- it->it_op == IT_UNLINK ? S_IFREG : S_IFDIR,
- de->d_name.name, de->d_name.len);
-
- req->rq_replen = lustre_msg_size(3, repsize);
- } else if (it->it_op & (IT_GETATTR | IT_RENAME | IT_LINK |
- IT_OPEN | IT_SETATTR | IT_LOOKUP | IT_READLINK)) {
- size[2] = sizeof(struct mds_body);
- size[3] = de->d_name.len + 1;
-
- req = ptlrpc_prep_req(class_conn2cliimp(conn), LDLM_ENQUEUE, 4,
- size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- /* pack the intent */
- lit = lustre_msg_buf(req->rq_reqmsg, 1);
- lit->opc = NTOH__u64((__u64)it->it_op);
-
- /* pack the intended request */
- mds_getattr_pack(req, 2, dir, de->d_name.name, de->d_name.len);
-
- /* get ready for the reply */
- req->rq_replen = lustre_msg_size(3, repsize);
- } else if (it->it_op == IT_READDIR) {
- req = ptlrpc_prep_req(class_conn2cliimp(conn), LDLM_ENQUEUE, 1,
- size, NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- /* get ready for the reply */
- req->rq_replen = lustre_msg_size(1, repsize);
- } else {
- LBUG();
- RETURN(-EINVAL);
- }
-
- rc = ldlm_cli_enqueue(conn, req, obddev->obd_namespace, NULL, res_id,
- lock_type, NULL, 0, lock_mode, &flags,
- ldlm_completion_ast, mdc_blocking_ast, data,
- datalen, lockh);
-
- if (it->it_op != IT_READDIR) {
- /* XXX This should become a lustre_msg flag, but for now... */
- __u32 *opp = lustre_msg_buf(req->rq_reqmsg, 2);
- *opp |= REINT_REPLAYING;
- }
-
- if (rc == -ENOENT) {
- /* This can go when we're sure that this can never happen */
- LBUG();
- }
- if (rc == ELDLM_LOCK_ABORTED) {
- lock_mode = 0;
- memset(lockh, 0, sizeof(*lockh));
- /* rc = 0 */
- } else if (rc != 0) {
- CERROR("ldlm_cli_enqueue: %d\n", rc);
- RETURN(rc);
- } else {
- /* The server almost certainly gave us a lock other than the one
- * that we asked for. If we already have a matching lock, then
- * cancel this one--we don't need two. */
- struct ldlm_lock *lock = ldlm_handle2lock(lockh);
- struct lustre_handle lockh2;
- LASSERT(lock);
-
- LDLM_DEBUG(lock, "matching against this");
-
- memcpy(&lockh2, lockh, sizeof(lockh2));
- if (ldlm_lock_match(NULL, NULL, LDLM_PLAIN, NULL, 0, LCK_NL,
- &lockh2)) {
- /* We already have a lock; cancel the old one */
- ldlm_lock_decref(lockh, lock_mode);
- ldlm_cli_cancel(lockh);
- memcpy(lockh, &lockh2, sizeof(lockh2));
- }
- LDLM_LOCK_PUT(lock);
- }
-
- /* On replay, we don't want the lock granted. */
- lockreq = lustre_msg_buf(req->rq_reqmsg, 0);
- lockreq->lock_flags |= LDLM_FL_INTENT_ONLY;
-
- dlm_rep = lustre_msg_buf(req->rq_repmsg, 0);
- it->it_disposition = (int) dlm_rep->lock_policy_res1;
- it->it_status = (int) dlm_rep->lock_policy_res2;
- it->it_lock_mode = lock_mode;
- it->it_data = req;
-
- RETURN(0);
-}
-
-int mdc_cancel_unused(struct lustre_handle *conn, struct inode *inode,
- int flags)
-{
- __u64 res_id[RES_NAME_SIZE] = {inode->i_ino, inode->i_generation};
- struct obd_device *obddev = class_conn2obd(conn);
- ENTRY;
- RETURN(ldlm_cli_cancel_unused(obddev->obd_namespace, res_id, flags));
-}
-
-struct replay_open_data {
- struct lustre_handle *fh;
-};
-
-static void mdc_replay_open(struct ptlrpc_request *req)
-{
- int offset;
- struct replay_open_data *saved;
- struct mds_body *body = lustre_msg_buf(req->rq_repmsg, 0);
-
- if (lustre_msg_get_op_flags(req->rq_reqmsg) & MDS_OPEN_HAS_EA)
- offset = 2;
- else
- offset = 1;
-
- saved = lustre_msg_buf(req->rq_reqmsg, offset);
- mds_unpack_body(body);
- CDEBUG(D_HA, "updating from "LPD64"/"LPD64" to "LPD64"/"LPD64"\n",
- saved->fh->addr, saved->fh->cookie,
- body->handle.addr, body->handle.cookie);
- memcpy(saved->fh, &body->handle, sizeof(body->handle));
-}
-
-int mdc_open(struct lustre_handle *conn, obd_id ino, int type, int flags,
- struct lov_mds_md *lmm, int lmm_size, struct lustre_handle *fh,
- struct ptlrpc_request **request)
-{
- struct mds_body *body;
- struct replay_open_data *replay_data;
- int rc, size[3] = {sizeof(*body), sizeof(*replay_data)}, bufcount = 2;
- struct ptlrpc_request *req;
- ENTRY;
-
- if (lmm && lmm_size) {
- bufcount = 3;
- size[2] = size[1]; /* shuffle the spare data along */
- size[1] = lmm_size;
- }
-
- req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_OPEN, bufcount, size,
- NULL);
- if (!req)
- GOTO(out, rc = -ENOMEM);
-
- req->rq_flags |= PTL_RPC_FL_REPLAY;
- body = lustre_msg_buf(req->rq_reqmsg, 0);
-
- ll_ino2fid(&body->fid1, ino, 0, type);
- body->flags = HTON__u32(flags);
- memcpy(&body->handle, fh, sizeof(body->handle));
-
- if (lmm && lmm_size) {
- CDEBUG(D_INODE, "sending %u bytes MD for ino "LPU64"\n",
- lmm_size, ino);
- lustre_msg_set_op_flags(req->rq_reqmsg, MDS_OPEN_HAS_EA);
- memcpy(lustre_msg_buf(req->rq_reqmsg, 1), lmm, lmm_size);
- body->flags |= HTON__u32(OBD_MD_FLEASIZE);
- }
-
- req->rq_replen = lustre_msg_size(1, size);
-
- rc = ptlrpc_queue_wait(req);
- if (!rc) {
- body = lustre_msg_buf(req->rq_repmsg, 0);
- mds_unpack_body(body);
- memcpy(fh, &body->handle, sizeof(*fh));
- }
-
- /* If open is replayed, we need to fix up the fh. */
- req->rq_replay_cb = mdc_replay_open;
- replay_data = lustre_msg_buf(req->rq_reqmsg, lmm ? 2 : 1);
- replay_data->fh = fh;
-
- EXIT;
- out:
- *request = req;
- return rc;
-}
-
-int mdc_close(struct lustre_handle *conn, obd_id ino, int type,
- struct lustre_handle *fh, struct ptlrpc_request **request)
-{
- struct mds_body *body;
- int rc, size = sizeof(*body);
- struct ptlrpc_request *req;
- ENTRY;
-
- req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_CLOSE, 1, &size,
- NULL);
- if (!req)
- GOTO(out, rc = -ENOMEM);
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- ll_ino2fid(&body->fid1, ino, 0, type);
- memcpy(&body->handle, fh, sizeof(body->handle));
-
- req->rq_replen = lustre_msg_size(0, NULL);
-
- rc = ptlrpc_queue_wait(req);
-
- EXIT;
- out:
- *request = req;
- return rc;
-}
-
-int mdc_readpage(struct lustre_handle *conn, obd_id ino, int type, __u64 offset,
- char *addr, struct ptlrpc_request **request)
-{
- struct ptlrpc_connection *connection =
- client_conn2cli(conn)->cl_import.imp_connection;
- struct ptlrpc_request *req = NULL;
- struct ptlrpc_bulk_desc *desc = NULL;
- struct ptlrpc_bulk_page *bulk = NULL;
- struct mds_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- CDEBUG(D_INODE, "inode: %ld\n", (long)ino);
-
- desc = ptlrpc_prep_bulk(connection);
- if (desc == NULL)
- GOTO(out, rc = -ENOMEM);
-
- req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_READPAGE, 1, &size,
- NULL);
- if (!req)
- GOTO(out2, rc = -ENOMEM);
-
- bulk = ptlrpc_prep_bulk_page(desc);
- bulk->bp_buflen = PAGE_SIZE;
- bulk->bp_buf = addr;
- bulk->bp_xid = req->rq_xid;
- desc->bd_portal = MDS_BULK_PORTAL;
-
- rc = ptlrpc_register_bulk(desc);
- if (rc) {
- CERROR("couldn't setup bulk sink: error %d.\n", rc);
- GOTO(out2, rc);
- }
-
- mds_readdir_pack(req, offset, ino, type);
-
- req->rq_replen = lustre_msg_size(1, &size);
- rc = ptlrpc_queue_wait(req);
- if (rc) {
- ptlrpc_abort_bulk(desc);
- GOTO(out2, rc);
- } else {
- body = lustre_msg_buf(req->rq_repmsg, 0);
- mds_unpack_body(body);
- }
-
- EXIT;
- out2:
- ptlrpc_free_bulk(desc);
- out:
- *request = req;
- return rc;
-}
-
-static int mdc_statfs(struct lustre_handle *conn, struct obd_statfs *osfs)
-{
- struct ptlrpc_request *req;
- int rc, size = sizeof(*osfs);
- ENTRY;
-
- req = ptlrpc_prep_req(class_conn2cliimp(conn), MDS_STATFS, 0, NULL,
- NULL);
- if (!req)
- RETURN(-ENOMEM);
-
- req->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(req);
-
- if (rc)
- GOTO(out, rc);
-
- obd_statfs_unpack(osfs, lustre_msg_buf(req->rq_repmsg, 0));
-
- EXIT;
-out:
- ptlrpc_req_finished(req);
-
- return rc;
-}
-
-static int mdc_attach(struct obd_device *dev, obd_count len, void *data)
-{
- return lprocfs_reg_obd(dev, status_var_nm_1, dev);
-}
-
-static int mdc_detach(struct obd_device *dev)
-{
- return lprocfs_dereg_obd(dev);
-}
-
-static int mdc_recover(struct obd_import *imp, int phase)
-{
- int rc;
- ENTRY;
-
- switch(phase) {
- case PTLRPC_RECOVD_PHASE_PREPARE:
- ldlm_cli_cancel_unused(imp->imp_obd->obd_namespace,
- NULL, LDLM_FL_LOCAL_ONLY);
- RETURN(0);
- case PTLRPC_RECOVD_PHASE_RECOVER:
- rc = ptlrpc_reconnect_import(imp, MDS_CONNECT);
- if (rc == EALREADY)
- RETURN(ptlrpc_replay(imp, 0));
- if (rc)
- RETURN(rc);
-
- rc = ptlrpc_replay(imp, 0 /* no last flag*/);
- if (rc)
- RETURN(rc);
-
- rc = ldlm_replay_locks(imp);
- if (rc)
- RETURN(rc);
-
- spin_lock(&imp->imp_lock);
- imp->imp_level = LUSTRE_CONN_FULL;
- spin_unlock(&imp->imp_lock);
-
- ptlrpc_wake_delayed(imp);
-
- rc = ptlrpc_resend(imp);
- if (rc)
- RETURN(rc);
-
- RETURN(0);
- default:
- RETURN(-EINVAL);
- }
-}
-
-static int mdc_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- struct obd_import *imp = &obd->u.cli.cl_import;
- imp->imp_recover = mdc_recover;
- return client_obd_connect(conn, obd, cluuid, recovd, recover);
-}
-
-struct obd_ops mdc_obd_ops = {
- o_attach: mdc_attach,
- o_detach: mdc_detach,
- o_setup: client_obd_setup,
- o_cleanup: client_obd_cleanup,
- o_connect: mdc_connect,
- o_disconnect: client_obd_disconnect,
- o_statfs: mdc_statfs,
-};
-
-static int __init ptlrpc_request_init(void)
-{
- return class_register_type(&mdc_obd_ops, status_class_var,
- LUSTRE_MDC_NAME);
-}
-
-static void __exit ptlrpc_request_exit(void)
-{
- class_unregister_type(LUSTRE_MDC_NAME);
-}
-
-MODULE_AUTHOR("Cluster File Systems <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Metadata Client v1.0");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(d_delete_aliases);
-EXPORT_SYMBOL(mdc_getstatus);
-EXPORT_SYMBOL(mdc_getlovinfo);
-EXPORT_SYMBOL(mdc_enqueue);
-EXPORT_SYMBOL(mdc_cancel_unused);
-EXPORT_SYMBOL(mdc_getattr);
-EXPORT_SYMBOL(mdc_create);
-EXPORT_SYMBOL(mdc_unlink);
-EXPORT_SYMBOL(mdc_rename);
-EXPORT_SYMBOL(mdc_link);
-EXPORT_SYMBOL(mdc_readpage);
-EXPORT_SYMBOL(mdc_setattr);
-EXPORT_SYMBOL(mdc_close);
-EXPORT_SYMBOL(mdc_open);
-
-EXPORT_SYMBOL(mdc_store_inode_generation);
-
-module_init(ptlrpc_request_init);
-module_exit(ptlrpc_request_exit);
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=
-
-if LINUX25
-FSMOD = mds_ext3
-else
-FSMOD = mds_extN
-endif
-
-MODULE = mds
-modulefs_DATA = mds.o $(FSMOD).o
-EXTRA_PROGRAMS = mds $(FSMOD)
-
-LINX= mds_updates.c simple.c ll_pack.c target.c
-
-ll_pack.c:
- test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c
-mds_updates.c:
- test -e mds_updates.c || ln -sf $(top_srcdir)/lib/mds_updates.c
-simple.c:
- test -e simple.c || ln -sf $(top_srcdir)/lib/simple.c
-target.c:
- test -e target.c || ln -sf $(top_srcdir)/lib/target.c
-
-mds_SOURCES = mds_lov.c handler.c mds_reint.c mds_fs.c lproc_mds.c $(LINX)
-
-include $(top_srcdir)/Rules
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * lustre/mds/handler.c
- * Lustre Metadata Server (mds) request handler
- *
- * Copyright (c) 2001, 2002 Cluster File Systems, Inc.
- * Author: Peter Braam <braam@clusterfs.com>
- * Author: Andreas Dilger <adilger@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- * Author: Mike Shaver <shaver@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_MDS
-
-#include <linux/module.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_dlm.h>
-#include <linux/init.h>
-#include <linux/obd_class.h>
-#include <linux/random.h>
-#include <linux/locks.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
-#include <linux/buffer_head.h>
-#endif
-#include <linux/obd_lov.h>
-#include <linux/lprocfs_status.h>
-
-static kmem_cache_t *mds_file_cache;
-
-extern int mds_get_lovtgts(struct mds_obd *obd, int tgt_count,
- obd_uuid_t *uuidarray);
-extern int mds_get_lovdesc(struct mds_obd *obd, struct lov_desc *desc);
-extern void mds_start_transno(struct mds_obd *mds);
-extern int mds_finish_transno(struct mds_obd *mds, void *handle,
- struct ptlrpc_request *req, int rc);
-static int mds_cleanup(struct obd_device * obddev);
-
-extern struct lprocfs_vars status_var_nm_1[];
-extern struct lprocfs_vars status_class_var[];
-
-inline struct mds_obd *mds_req2mds(struct ptlrpc_request *req)
-{
- return &req->rq_export->exp_obd->u.mds;
-}
-
-static int mds_bulk_timeout(void *data)
-{
- struct ptlrpc_bulk_desc *desc = data;
-
- ENTRY;
- recovd_conn_fail(desc->bd_connection);
- RETURN(1);
-}
-
-/* Assumes caller has already pushed into the kernel filesystem context */
-static int mds_sendpage(struct ptlrpc_request *req, struct file *file,
- __u64 offset)
-{
- int rc = 0;
- struct mds_obd *mds = mds_req2mds(req);
- struct ptlrpc_bulk_desc *desc;
- struct ptlrpc_bulk_page *bulk;
- struct l_wait_info lwi;
- char *buf;
- ENTRY;
-
- desc = ptlrpc_prep_bulk(req->rq_connection);
- if (desc == NULL)
- GOTO(out, rc = -ENOMEM);
-
- bulk = ptlrpc_prep_bulk_page(desc);
- if (bulk == NULL)
- GOTO(cleanup_bulk, rc = -ENOMEM);
-
- OBD_ALLOC(buf, PAGE_SIZE);
- if (buf == NULL)
- GOTO(cleanup_bulk, rc = -ENOMEM);
-
- rc = mds_fs_readpage(mds, file, buf, PAGE_SIZE, (loff_t *)&offset);
-
- if (rc != PAGE_SIZE)
- GOTO(cleanup_buf, rc = -EIO);
-
- bulk->bp_xid = req->rq_xid;
- bulk->bp_buf = buf;
- bulk->bp_buflen = PAGE_SIZE;
- desc->bd_portal = MDS_BULK_PORTAL;
-
- rc = ptlrpc_send_bulk(desc);
- if (rc)
- GOTO(cleanup_buf, rc);
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_SENDPAGE)) {
- CERROR("obd_fail_loc=%x, fail operation rc=%d\n",
- OBD_FAIL_MDS_SENDPAGE, rc);
- ptlrpc_abort_bulk(desc);
- GOTO(cleanup_buf, rc);
- }
-
- lwi = LWI_TIMEOUT(obd_timeout * HZ, mds_bulk_timeout, desc);
- rc = l_wait_event(desc->bd_waitq, desc->bd_flags & PTL_BULK_FL_SENT,
- &lwi);
- if (rc) {
- if (rc != -ETIMEDOUT)
- LBUG();
- GOTO(cleanup_buf, rc);
- }
-
- EXIT;
- cleanup_buf:
- OBD_FREE(buf, PAGE_SIZE);
- cleanup_bulk:
- ptlrpc_free_bulk(desc);
- out:
- return rc;
-}
-
-/*
- * Look up a named entry in a directory, and get an LDLM lock on it.
- * 'dir' is a inode for which an LDLM lock has already been taken.
- *
- * If we do not need an exclusive or write lock on this entry (e.g.
- * a read lock for attribute lookup only) then we do not hold the
- * directory semaphore on return. It is up to the caller to know what
- * type of lock it is getting, and clean up appropriately.
- */
-struct dentry *mds_name2locked_dentry(struct obd_device *obd,
- struct dentry *dir, struct vfsmount **mnt,
- char *name, int namelen, int lock_mode,
- struct lustre_handle *lockh,
- int dir_lock_mode)
-{
- struct dentry *dchild;
- int flags = 0, rc;
- __u64 res_id[3] = {0};
- ENTRY;
-
- down(&dir->d_inode->i_sem);
- dchild = lookup_one_len(name, dir, namelen);
- if (IS_ERR(dchild)) {
- CERROR("child lookup error %ld\n", PTR_ERR(dchild));
- up(&dir->d_inode->i_sem);
- LBUG();
- RETURN(dchild);
- }
- if (dir_lock_mode != LCK_EX && dir_lock_mode != LCK_PW) {
- up(&dir->d_inode->i_sem);
- ldlm_lock_decref(lockh, dir_lock_mode);
- }
-
- if (lock_mode == 0 || !dchild->d_inode)
- RETURN(dchild);
-
- res_id[0] = dchild->d_inode->i_ino;
- res_id[1] = dchild->d_inode->i_generation;
- rc = ldlm_match_or_enqueue(NULL, NULL, obd->obd_namespace, NULL,
- res_id, LDLM_PLAIN, NULL, 0, lock_mode,
- &flags, ldlm_completion_ast,
- mds_blocking_ast, NULL, 0, lockh);
- if (rc != ELDLM_OK) {
- l_dput(dchild);
- up(&dir->d_inode->i_sem);
- RETURN(ERR_PTR(-ENOLCK)); /* XXX translate ldlm code */
- }
-
- RETURN(dchild);
-}
-
-struct dentry *mds_fid2locked_dentry(struct obd_device *obd, struct ll_fid *fid,
- struct vfsmount **mnt, int lock_mode,
- struct lustre_handle *lockh)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct dentry *de = mds_fid2dentry(mds, fid, mnt), *retval = de;
- int flags = 0, rc;
- __u64 res_id[3] = {0};
- ENTRY;
-
- if (IS_ERR(de))
- RETURN(de);
-
- res_id[0] = de->d_inode->i_ino;
- res_id[1] = de->d_inode->i_generation;
- rc = ldlm_match_or_enqueue(NULL, NULL, obd->obd_namespace, NULL,
- res_id, LDLM_PLAIN, NULL, 0, lock_mode,
- &flags, ldlm_completion_ast,
- mds_blocking_ast, NULL, 0, lockh);
- if (rc != ELDLM_OK) {
- l_dput(de);
- retval = ERR_PTR(-ENOLCK); /* XXX translate ldlm code */
- }
-
- RETURN(retval);
-}
-
-#ifndef DCACHE_DISCONNECTED
-#define DCACHE_DISCONNECTED DCACHE_NFSD_DISCONNECTED
-#endif
-
-/* Look up an entry by inode number. */
-struct dentry *mds_fid2dentry(struct mds_obd *mds, struct ll_fid *fid,
- struct vfsmount **mnt)
-{
- /* stolen from NFS */
- struct super_block *sb = mds->mds_sb;
- unsigned long ino = fid->id;
- __u32 generation = fid->generation;
- struct inode *inode;
- struct list_head *lp;
- struct dentry *result;
-
- if (ino == 0)
- RETURN(ERR_PTR(-ESTALE));
-
- inode = iget(sb, ino);
- if (inode == NULL)
- RETURN(ERR_PTR(-ENOMEM));
-
- CDEBUG(D_DENTRY, "--> mds_fid2dentry: sb %p\n", inode->i_sb);
-
- if (is_bad_inode(inode) ||
- (generation && inode->i_generation != generation)) {
- /* we didn't find the right inode.. */
- CERROR("bad inode %lu, link: %d ct: %d or version %u/%u\n",
- inode->i_ino, inode->i_nlink,
- atomic_read(&inode->i_count), inode->i_generation,
- generation);
- iput(inode);
- RETURN(ERR_PTR(-ENOENT));
- }
-
- /* now to find a dentry. If possible, get a well-connected one */
- if (mnt)
- *mnt = mds->mds_vfsmnt;
- spin_lock(&dcache_lock);
- list_for_each(lp, &inode->i_dentry) {
- result = list_entry(lp, struct dentry, d_alias);
- if (!(result->d_flags & DCACHE_DISCONNECTED)) {
- dget_locked(result);
- result->d_vfs_flags |= DCACHE_REFERENCED;
- spin_unlock(&dcache_lock);
- iput(inode);
- if (mnt)
- mntget(*mnt);
- return result;
- }
- }
- spin_unlock(&dcache_lock);
- result = d_alloc_root(inode);
- if (result == NULL) {
- iput(inode);
- return ERR_PTR(-ENOMEM);
- }
- if (mnt)
- mntget(*mnt);
- result->d_flags |= DCACHE_DISCONNECTED;
- return result;
-}
-
-/* Establish a connection to the MDS.
- *
- * This will set up an export structure for the client to hold state data
- * about that client, like open files, the last operation number it did
- * on the server, etc.
- */
-static int mds_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- struct obd_export *exp;
- struct mds_export_data *med;
- struct mds_client_data *mcd;
- struct list_head *p;
- int rc;
- ENTRY;
-
- if (!conn || !obd || !cluuid)
- RETURN(-EINVAL);
-
- MOD_INC_USE_COUNT;
-
- spin_lock(&obd->obd_dev_lock);
- list_for_each(p, &obd->obd_exports) {
- exp = list_entry(p, struct obd_export, exp_obd_chain);
- mcd = exp->exp_mds_data.med_mcd;
- if (!mcd) {
- CERROR("FYI: NULL mcd - simultaneous connects\n");
- continue;
- }
- if (!memcmp(cluuid, mcd->mcd_uuid, sizeof mcd->mcd_uuid)) {
- /* XXX make handle-found-export a subroutine */
- LASSERT(exp->exp_obd == obd);
-
- spin_unlock(&obd->obd_dev_lock);
- if (exp->exp_connection) {
- struct lustre_handle *hdl;
- hdl = &exp->exp_ldlm_data.led_import.imp_handle;
- /* Might be a re-connect after a partition. */
- if (!memcmp(conn, hdl, sizeof *conn)) {
- CERROR("%s reconnecting\n", cluuid);
- conn->addr = (__u64) (unsigned long)exp;
- conn->cookie = exp->exp_cookie;
- rc = EALREADY;
- } else {
- CERROR("%s reconnecting from %s, "
- "handle mismatch (ours %Lx/%Lx, "
- "theirs %Lx/%Lx)\n", cluuid,
- exp->exp_connection->
- c_remote_uuid, hdl->addr,
- hdl->cookie, conn->addr,
- conn->cookie);
- /* XXX disconnect them here? */
- memset(conn, 0, sizeof *conn);
- rc = -EALREADY;
- }
- MOD_DEC_USE_COUNT;
- RETURN(rc);
- }
- conn->addr = (__u64) (unsigned long)exp;
- conn->cookie = exp->exp_cookie;
- CDEBUG(D_INFO, "existing export for UUID '%s' at %p\n",
- cluuid, exp);
- CDEBUG(D_IOCTL,"connect: addr %Lx cookie %Lx\n",
- (long long)conn->addr, (long long)conn->cookie);
- RETURN(0);
- }
- }
- spin_unlock(&obd->obd_dev_lock);
-
- if (obd->u.mds.mds_recoverable_clients != 0) {
- CERROR("denying connection for new client %s: in recovery\n",
- cluuid);
- MOD_DEC_USE_COUNT;
- RETURN(-EBUSY);
- }
-
- /* XXX There is a small race between checking the list and adding a
- * new connection for the same UUID, but the real threat (list
- * corruption when multiple different clients connect) is solved.
- *
- * There is a second race between adding the export to the list,
- * and filling in the client data below. Hence skipping the case
- * of NULL mcd above. We should already be controlling multiple
- * connects at the client, and we can't hold the spinlock over
- * memory allocations without risk of deadlocking.
- */
- rc = class_connect(conn, obd, cluuid);
- if (rc)
- GOTO(out_dec, rc);
- exp = class_conn2export(conn);
- LASSERT(exp);
- med = &exp->exp_mds_data;
-
- OBD_ALLOC(mcd, sizeof(*mcd));
- if (!mcd) {
- CERROR("mds: out of memory for client data\n");
- GOTO(out_export, rc = -ENOMEM);
- }
-
- memcpy(mcd->mcd_uuid, cluuid, sizeof(mcd->mcd_uuid));
- med->med_mcd = mcd;
-
- INIT_LIST_HEAD(&med->med_open_head);
- spin_lock_init(&med->med_open_lock);
-
- rc = mds_client_add(&obd->u.mds, med, -1);
- if (rc)
- GOTO(out_mcd, rc);
-
- RETURN(0);
-
-out_mcd:
- OBD_FREE(mcd, sizeof(*mcd));
-out_export:
- class_disconnect(conn);
-out_dec:
- MOD_DEC_USE_COUNT;
-
- return rc;
-}
-
-/* Call with med->med_open_lock held, please. */
-inline int mds_close_mfd(struct mds_file_data *mfd, struct mds_export_data *med)
-{
- struct file *file = mfd->mfd_file;
- LASSERT(file->private_data == mfd);
-
- list_del(&mfd->mfd_list);
- mfd->mfd_servercookie = DEAD_HANDLE_MAGIC;
- kmem_cache_free(mds_file_cache, mfd);
-
- return filp_close(file, 0);
-}
-
-static int mds_disconnect(struct lustre_handle *conn)
-{
- struct obd_export *export = class_conn2export(conn);
- struct list_head *tmp, *n;
- struct mds_export_data *med = &export->exp_mds_data;
- int rc;
- ENTRY;
-
- /*
- * Close any open files.
- */
- spin_lock(&med->med_open_lock);
- list_for_each_safe(tmp, n, &med->med_open_head) {
- struct mds_file_data *mfd =
- list_entry(tmp, struct mds_file_data, mfd_list);
- rc = mds_close_mfd(mfd, med);
- if (rc) {
- /* XXX better diagnostics, with file path and stuff */
- CDEBUG(D_INODE, "Error %d closing mfd %p\n", rc, mfd);
- }
- }
- spin_unlock(&med->med_open_lock);
-
- ldlm_cancel_locks_for_export(export);
- mds_client_free(export);
-
- rc = class_disconnect(conn);
- if (!rc)
- MOD_DEC_USE_COUNT;
-
- RETURN(rc);
-}
-
-/*
- * XXX This is NOT guaranteed to flush all transactions to disk (even though
- * it is equivalent to calling sync()) because it only _starts_ the flush
- * and does not wait for completion. It's better than nothing though.
- * What we really want is a mild form of fsync_dev_lockfs(), but it is
- * non-standard, or enabling do_sync_supers in ext3, just for this call.
- */
-static void mds_fsync_super(struct super_block *sb)
-{
- lock_kernel();
- lock_super(sb);
- if (sb->s_dirt && sb->s_op && sb->s_op->write_super)
- sb->s_op->write_super(sb);
- unlock_super(sb);
- unlock_kernel();
-}
-
-static int mds_getstatus(struct ptlrpc_request *req)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct mds_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_GETSTATUS_PACK)) {
- CERROR("mds: out of memory for message: size=%d\n", size);
- req->rq_status = -ENOMEM;
- RETURN(0);
- }
-
- /* Flush any outstanding transactions to disk so the client will
- * get the latest last_committed value and can drop their local
- * requests if they have any. This would be fsync_super() if it
- * was exported.
- */
- mds_fsync_super(mds->mds_sb);
-
- body = lustre_msg_buf(req->rq_repmsg, 0);
- memcpy(&body->fid1, &mds->mds_rootfid, sizeof(body->fid1));
-
- /* the last_committed and last_xid fields are filled in for all
- * replies already - no need to do so here also.
- */
- RETURN(0);
-}
-
-static int mds_getlovinfo(struct ptlrpc_request *req)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct mds_status_req *streq;
- struct lov_desc *desc;
- int tgt_count;
- int rc, size[2] = {sizeof(*desc)};
- ENTRY;
-
- streq = lustre_msg_buf(req->rq_reqmsg, 0);
- streq->flags = NTOH__u32(streq->flags);
- streq->repbuf = NTOH__u32(streq->repbuf);
- size[1] = streq->repbuf;
-
- rc = lustre_pack_msg(2, size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc) {
- CERROR("mds: out of memory for message: size=%d\n", size[1]);
- req->rq_status = -ENOMEM;
- RETURN(0);
- }
-
- desc = lustre_msg_buf(req->rq_repmsg, 0);
- rc = mds_get_lovdesc(mds, desc);
- if (rc) {
- req->rq_status = rc;
- RETURN(0);
- }
-
- tgt_count = le32_to_cpu(desc->ld_tgt_count);
- if (tgt_count * sizeof(obd_uuid_t) > streq->repbuf) {
- CERROR("too many targets, enlarge client buffers\n");
- req->rq_status = -ENOSPC;
- RETURN(0);
- }
-
- /* XXX the MDS should not really know about this */
- mds->mds_max_mdsize = lov_mds_md_size(tgt_count);
- rc = mds_get_lovtgts(mds, tgt_count,
- lustre_msg_buf(req->rq_repmsg, 1));
- if (rc) {
- CERROR("get_lovtgts error %d\n", rc);
- req->rq_status = rc;
- RETURN(0);
- }
- RETURN(0);
-}
-
-int mds_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
- void *data, __u32 data_len, int flag)
-{
- int do_ast;
- ENTRY;
-
- if (flag == LDLM_CB_CANCELING) {
- /* Don't need to do anything here. */
- RETURN(0);
- }
-
- /* XXX layering violation! -phil */
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- lock->l_flags |= LDLM_FL_CBPENDING;
- do_ast = (!lock->l_readers && !lock->l_writers);
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
-
- if (do_ast) {
- struct lustre_handle lockh;
- int rc;
-
- LDLM_DEBUG(lock, "already unused, calling ldlm_cli_cancel");
- ldlm_lock2handle(lock, &lockh);
- rc = ldlm_cli_cancel(&lockh);
- if (rc < 0)
- CERROR("ldlm_cli_cancel: %d\n", rc);
- } else
- LDLM_DEBUG(lock, "Lock still has references, will be"
- "cancelled later");
- RETURN(0);
-}
-
-int mds_pack_md(struct mds_obd *mds, struct ptlrpc_request *req,
- int offset, struct mds_body *body, struct inode *inode)
-{
- struct lov_mds_md *lmm;
- int lmm_size = req->rq_repmsg->buflens[offset];
- int rc;
-
- if (lmm_size == 0) {
- CDEBUG(D_INFO, "no space reserved for inode %u MD\n", inode->i_ino);
- RETURN(0);
- }
-
- lmm = lustre_msg_buf(req->rq_repmsg, offset);
-
- /* I don't really like this, but it is a sanity check on the client
- * MD request. However, if the client doesn't know how much space
- * to reserve for the MD, this shouldn't be fatal either...
- */
- if (lmm_size > mds->mds_max_mdsize) {
- CERROR("Reading MD for inode %u of %d bytes > max %d\n",
- inode->i_ino, lmm_size, mds->mds_max_mdsize);
- // RETURN(-EINVAL);
- }
-
- /* We don't need to store the reply size, because this buffer is
- * discarded right after unpacking, and the LOV can figure out the
- * size itself from the ost count.
- */
- if ((rc = mds_fs_get_md(mds, inode, lmm, lmm_size)) < 0) {
- CDEBUG(D_INFO, "No md for ino %u: rc = %d\n", inode->i_ino, rc);
- } else if (rc > 0) {
- body->valid |= OBD_MD_FLEASIZE;
- rc = 0;
- }
-
- return rc;
-}
-
-static int mds_getattr_internal(struct mds_obd *mds, struct dentry *dentry,
- struct ptlrpc_request *req,
- struct mds_body *reqbody, int reply_off)
-{
- struct mds_body *body;
- struct inode *inode = dentry->d_inode;
- int rc = 0;
- ENTRY;
-
- if (inode == NULL)
- RETURN(-ENOENT);
-
- body = lustre_msg_buf(req->rq_repmsg, reply_off);
-
- mds_pack_inode2fid(&body->fid1, inode);
- mds_pack_inode2body(body, inode);
-
- if (S_ISREG(inode->i_mode)) {
- rc = mds_pack_md(mds, req, reply_off + 1, body, inode);
- } else if (S_ISLNK(inode->i_mode) && reqbody->valid & OBD_MD_LINKNAME) {
- char *symname = lustre_msg_buf(req->rq_repmsg, reply_off + 1);
- int len = req->rq_repmsg->buflens[reply_off + 1];
-
- rc = inode->i_op->readlink(dentry, symname, len);
- if (rc < 0) {
- CERROR("readlink failed: %d\n", rc);
- } else {
- CDEBUG(D_INODE, "read symlink dest %s\n", symname);
- body->valid |= OBD_MD_LINKNAME;
- }
- }
- RETURN(rc);
-}
-
-static int mds_getattr_name(int offset, struct ptlrpc_request *req)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct obd_device *obd = req->rq_export->exp_obd;
- struct obd_run_ctxt saved;
- struct mds_body *body;
- struct dentry *de = NULL, *dchild = NULL;
- struct inode *dir;
- struct lustre_handle lockh;
- char *name;
- int namelen, flags = 0, lock_mode, rc = 0;
- struct obd_ucred uc;
- __u64 res_id[3] = {0, 0, 0};
- ENTRY;
-
- LASSERT(!strcmp(req->rq_export->exp_obd->obd_type->typ_name, "mds"));
-
- if (req->rq_reqmsg->bufcount <= offset + 1) {
- LBUG();
- GOTO(out_pre_de, rc = -EINVAL);
- }
-
- body = lustre_msg_buf(req->rq_reqmsg, offset);
- name = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- namelen = req->rq_reqmsg->buflens[offset + 1];
- /* requests were at offset 2, replies go back at 1 */
- if (offset)
- offset = 1;
-
- uc.ouc_fsuid = body->fsuid;
- uc.ouc_fsgid = body->fsgid;
- uc.ouc_cap = body->capability;
- push_ctxt(&saved, &mds->mds_ctxt, &uc);
- de = mds_fid2dentry(mds, &body->fid1, NULL);
- if (IS_ERR(de)) {
- GOTO(out_pre_de, rc = -ENOENT);
- }
-
- dir = de->d_inode;
- CDEBUG(D_INODE, "parent ino %ld, name %*s\n", dir->i_ino,namelen,name);
-
- lock_mode = LCK_PR;
- res_id[0] = dir->i_ino;
- res_id[1] = dir->i_generation;
-
- rc = ldlm_lock_match(obd->obd_namespace, res_id, LDLM_PLAIN,
- NULL, 0, lock_mode, &lockh);
- if (rc == 0) {
- LDLM_DEBUG_NOLOCK("enqueue res "LPU64, res_id[0]);
- rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, NULL,
- res_id, LDLM_PLAIN, NULL, 0, lock_mode,
- &flags, ldlm_completion_ast,
- mds_blocking_ast, NULL, 0, &lockh);
- if (rc != ELDLM_OK) {
- CERROR("lock enqueue: err: %d\n", rc);
- GOTO(out_create_de, rc = -EIO);
- }
- }
- ldlm_lock_dump((void *)(unsigned long)lockh.addr);
-
- down(&dir->i_sem);
- dchild = lookup_one_len(name, de, namelen - 1);
- if (IS_ERR(dchild)) {
- CDEBUG(D_INODE, "child lookup error %ld\n", PTR_ERR(dchild));
- up(&dir->i_sem);
- GOTO(out_create_dchild, rc = PTR_ERR(dchild));
- }
-
- rc = mds_getattr_internal(mds, dchild, req, body, offset);
-
- EXIT;
-out_create_dchild:
- l_dput(dchild);
- up(&dir->i_sem);
- ldlm_lock_decref(&lockh, lock_mode);
-out_create_de:
- l_dput(de);
-out_pre_de:
- req->rq_status = rc;
- pop_ctxt(&saved, &mds->mds_ctxt, &uc);
- return 0;
-}
-
-static int mds_getattr(int offset, struct ptlrpc_request *req)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct obd_run_ctxt saved;
- struct dentry *de;
- struct inode *inode;
- struct mds_body *body;
- struct obd_ucred uc;
- int rc = 0, size[2] = {sizeof(*body)}, bufcount = 1;
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, offset);
- uc.ouc_fsuid = body->fsuid;
- uc.ouc_fsgid = body->fsgid;
- uc.ouc_cap = body->capability;
- push_ctxt(&saved, &mds->mds_ctxt, &uc);
- de = mds_fid2dentry(mds, &body->fid1, NULL);
- if (IS_ERR(de)) {
- rc = req->rq_status = -ENOENT;
- GOTO(out_pop, PTR_ERR(de));
- }
-
- inode = de->d_inode;
- if (S_ISREG(body->fid1.f_type)) {
- int rc = mds_fs_get_md(mds, inode, NULL, 0);
- CDEBUG(D_INODE, "got %d bytes MD data for inode %u\n",
- rc, inode->i_ino);
- if (rc < 0) {
- if (rc != -ENODATA)
- CERROR("error getting inode %u MD: rc = %d\n",
- inode->i_ino, rc);
- size[bufcount] = 0;
- } else if (rc > mds->mds_max_mdsize) {
- size[bufcount] = 0;
- CERROR("MD size %d larger than maximum possible %u\n",
- rc, mds->mds_max_mdsize);
- } else
- size[bufcount] = rc;
- bufcount++;
- } else if (body->valid & OBD_MD_LINKNAME) {
- size[bufcount] = MIN(inode->i_size + 1, body->size);
- bufcount++;
- CDEBUG(D_INODE, "symlink size: %d, reply space: %d\n",
- inode->i_size + 1, body->size);
- }
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETATTR_PACK)) {
- CERROR("failed MDS_GETATTR_PACK test\n");
- req->rq_status = -ENOMEM;
- GOTO(out, rc = -ENOMEM);
- }
-
- rc = lustre_pack_msg(bufcount, size, NULL, &req->rq_replen,
- &req->rq_repmsg);
- if (rc) {
- CERROR("out of memoryK\n");
- req->rq_status = rc;
- GOTO(out, rc);
- }
-
- req->rq_status = mds_getattr_internal(mds, de, req, body, 0);
-
-out:
- l_dput(de);
-out_pop:
- pop_ctxt(&saved, &mds->mds_ctxt, &uc);
- RETURN(rc);
-}
-
-static int mds_statfs(struct ptlrpc_request *req)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct obd_statfs *osfs;
- struct statfs sfs;
- int rc, size = sizeof(*osfs);
- ENTRY;
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_STATFS_PACK)) {
- CERROR("mds: statfs lustre_pack_msg failed: rc = %d\n", rc);
- GOTO(out, rc);
- }
-
- rc = mds_fs_statfs(mds, &sfs);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- GOTO(out, rc);
- }
- osfs = lustre_msg_buf(req->rq_repmsg, 0);
- memset(osfs, 0, size);
- statfs_pack(osfs, &sfs);
- obd_statfs_pack(osfs, osfs);
-
-out:
- req->rq_status = rc;
- RETURN(0);
-}
-
-static struct mds_file_data *mds_handle2mfd(struct lustre_handle *handle)
-{
- struct mds_file_data *mfd = NULL;
-
- if (!handle || !handle->addr)
- RETURN(NULL);
-
- mfd = (struct mds_file_data *)(unsigned long)(handle->addr);
- if (!kmem_cache_validate(mds_file_cache, mfd))
- RETURN(NULL);
-
- if (mfd->mfd_servercookie != handle->cookie)
- RETURN(NULL);
-
- return mfd;
-}
-
-static int mds_store_md(struct mds_obd *mds, struct ptlrpc_request *req,
- int offset, struct mds_body *body, struct inode *inode)
-{
- struct lov_mds_md *lmm = lustre_msg_buf(req->rq_reqmsg, offset);
- int lmm_size = req->rq_reqmsg->buflens[offset];
- struct obd_run_ctxt saved;
- struct obd_ucred uc;
- void *handle;
- int rc, rc2;
- ENTRY;
-
- /* I don't really like this, but it is a sanity check on the client
- * MD request.
- */
- if (lmm_size > mds->mds_max_mdsize) {
- CERROR("Saving MD for inode %u of %d bytes > max %d\n",
- inode->i_ino, lmm_size, mds->mds_max_mdsize);
- //RETURN(-EINVAL);
- }
-
- CDEBUG(D_INODE, "storing %d bytes MD for inode %u\n",
- lmm_size, inode->i_ino);
- uc.ouc_fsuid = body->fsuid;
- uc.ouc_fsgid = body->fsgid;
- uc.ouc_cap = body->capability;
- push_ctxt(&saved, &mds->mds_ctxt, &uc);
- mds_start_transno(mds);
- handle = mds_fs_start(mds, inode, MDS_FSOP_SETATTR);
- if (IS_ERR(handle)) {
- rc = PTR_ERR(handle);
- mds_finish_transno(mds, handle, req, rc);
- GOTO(out_ea, rc);
- }
-
- rc = mds_fs_set_md(mds, inode, handle, lmm, lmm_size);
- rc = mds_finish_transno(mds, handle, req, rc);
-
- rc2 = mds_fs_commit(mds, inode, handle);
- if (rc2 && !rc)
- rc = rc2;
-out_ea:
- pop_ctxt(&saved, &mds->mds_ctxt, &uc);
-
- RETURN(rc);
-}
-
-static int mds_open(struct ptlrpc_request *req)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct mds_body *body;
- struct mds_export_data *med;
- struct mds_file_data *mfd;
- struct dentry *de;
- struct file *file;
- struct vfsmount *mnt;
- __u32 flags;
- struct list_head *tmp;
- int rc, size = sizeof(*body);
- ENTRY;
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_OPEN_PACK)) {
- CERROR("test case OBD_FAIL_MDS_OPEN_PACK\n");
- req->rq_status = -ENOMEM;
- RETURN(-ENOMEM);
- }
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc) {
- CERROR("mds: pack error: rc = %d\n", rc);
- req->rq_status = rc;
- RETURN(rc);
- }
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
-
- /* was this animal open already and the client lost the reply? */
- /* XXX need some way to detect a reopen, to avoid locked list walks */
- med = &req->rq_export->exp_mds_data;
- spin_lock(&med->med_open_lock);
- list_for_each(tmp, &med->med_open_head) {
- mfd = list_entry(tmp, typeof(*mfd), mfd_list);
- if (!memcmp(&mfd->mfd_clienthandle, &body->handle,
- sizeof(mfd->mfd_clienthandle)) &&
- body->fid1.id == mfd->mfd_file->f_dentry->d_inode->i_ino) {
- de = mfd->mfd_file->f_dentry;
- spin_unlock(&med->med_open_lock);
- CERROR("Re opening "LPD64"\n", body->fid1.id);
- GOTO(out_pack, rc = 0);
- }
- }
- spin_unlock(&med->med_open_lock);
-
- mfd = kmem_cache_alloc(mds_file_cache, GFP_KERNEL);
- if (!mfd) {
- CERROR("mds: out of memory\n");
- req->rq_status = -ENOMEM;
- RETURN(0);
- }
-
- de = mds_fid2dentry(mds, &body->fid1, &mnt);
- if (IS_ERR(de))
- GOTO(out_free, rc = PTR_ERR(de));
-
- /* check if this inode has seen a delayed object creation */
- if (lustre_msg_get_op_flags(req->rq_reqmsg) & MDS_OPEN_HAS_EA) {
- rc = mds_store_md(mds, req, 1, body, de->d_inode);
- if (rc) {
- l_dput(de);
- mntput(mnt);
- GOTO(out_free, rc);
- }
- }
-
- flags = body->flags;
- /* dentry_open does a dput(de) and mntput(mnt) on error */
- file = dentry_open(de, mnt, flags & ~O_DIRECT);
- if (IS_ERR(file)) {
- rc = PTR_ERR(file);
- GOTO(out_free, 0);
- }
-
- file->private_data = mfd;
- mfd->mfd_file = file;
- memcpy(&mfd->mfd_clienthandle, &body->handle, sizeof(body->handle));
- get_random_bytes(&mfd->mfd_servercookie, sizeof(mfd->mfd_servercookie));
- spin_lock(&med->med_open_lock);
- list_add(&mfd->mfd_list, &med->med_open_head);
- spin_unlock(&med->med_open_lock);
-
-out_pack:
- body = lustre_msg_buf(req->rq_repmsg, 0);
- mds_pack_inode2fid(&body->fid1, de->d_inode);
- mds_pack_inode2body(body, de->d_inode);
- body->handle.addr = (__u64)(unsigned long)mfd;
- body->handle.cookie = mfd->mfd_servercookie;
- CDEBUG(D_INODE, "llite file "LPX64": addr %p, cookie "LPX64"\n",
- mfd->mfd_clienthandle.addr, mfd, mfd->mfd_servercookie);
- RETURN(0);
-
-out_free:
- mfd->mfd_servercookie = DEAD_HANDLE_MAGIC;
- kmem_cache_free(mds_file_cache, mfd);
- req->rq_status = rc;
- RETURN(0);
-}
-
-static int mds_close(struct ptlrpc_request *req)
-{
- struct mds_export_data *med = &req->rq_export->exp_mds_data;
- struct mds_body *body;
- struct mds_file_data *mfd;
- int rc;
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
-
- mfd = mds_handle2mfd(&body->handle);
- if (!mfd) {
- CERROR("no handle for file close "LPD64
- ": addr "LPX64", cookie "LPX64"\n",
- body->fid1.id, body->handle.addr, body->handle.cookie);
- RETURN(-ESTALE);
- }
-
- spin_lock(&med->med_open_lock);
- req->rq_status = mds_close_mfd(mfd, med);
- spin_unlock(&med->med_open_lock);
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_CLOSE_PACK)) {
- CERROR("test case OBD_FAIL_MDS_CLOSE_PACK\n");
- req->rq_status = -ENOMEM;
- RETURN(-ENOMEM);
- }
-
- rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc) {
- CERROR("mds: lustre_pack_msg: rc = %d\n", rc);
- req->rq_status = rc;
- }
-
- RETURN(0);
-}
-
-static int mds_readpage(struct ptlrpc_request *req)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct vfsmount *mnt;
- struct dentry *de;
- struct file *file;
- struct mds_body *body, *repbody;
- struct obd_run_ctxt saved;
- int rc, size = sizeof(*body);
- struct obd_ucred uc;
- ENTRY;
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_READPAGE_PACK)) {
- CERROR("mds: out of memory\n");
- GOTO(out, rc = -ENOMEM);
- }
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- uc.ouc_fsuid = body->fsuid;
- uc.ouc_fsgid = body->fsgid;
- uc.ouc_cap = body->capability;
- push_ctxt(&saved, &mds->mds_ctxt, &uc);
- de = mds_fid2dentry(mds, &body->fid1, &mnt);
- if (IS_ERR(de))
- GOTO(out_pop, rc = PTR_ERR(de));
-
- CDEBUG(D_INODE, "ino %ld\n", de->d_inode->i_ino);
-
- file = dentry_open(de, mnt, O_RDONLY | O_LARGEFILE);
- /* note: in case of an error, dentry_open puts dentry */
- if (IS_ERR(file))
- GOTO(out_pop, rc = PTR_ERR(file));
-
- repbody = lustre_msg_buf(req->rq_repmsg, 0);
- repbody->size = file->f_dentry->d_inode->i_size;
- repbody->valid = OBD_MD_FLSIZE;
-
- /* to make this asynchronous make sure that the handling function
- doesn't send a reply when this function completes. Instead a
- callback function would send the reply */
- /* note: in case of an error, dentry_open puts dentry */
- rc = mds_sendpage(req, file, body->size);
-
- filp_close(file, 0);
-out_pop:
- pop_ctxt(&saved, &mds->mds_ctxt, &uc);
-out:
- req->rq_status = rc;
- RETURN(0);
-}
-
-int mds_reint(struct ptlrpc_request *req, int offset)
-{
- int rc;
- struct mds_update_record rec;
-
- rc = mds_update_unpack(req, offset, &rec);
- if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_REINT_UNPACK)) {
- CERROR("invalid record\n");
- req->rq_status = -EINVAL;
- RETURN(0);
- }
- /* rc will be used to interrupt a for loop over multiple records */
- rc = mds_reint_rec(&rec, offset, req);
- return rc;
-}
-
-/* forward declaration */
-int mds_handle(struct ptlrpc_request *req);
-
-static int check_for_next_transno(struct mds_obd *mds)
-{
- struct ptlrpc_request *req;
- req = list_entry(mds->mds_recovery_queue.next,
- struct ptlrpc_request, rq_list);
- return req->rq_reqmsg->transno == mds->mds_next_recovery_transno;
-}
-
-static void process_recovery_queue(struct mds_obd *mds)
-{
- struct ptlrpc_request *req;
-
- for (;;) {
- spin_lock(&mds->mds_processing_task_lock);
- req = list_entry(mds->mds_recovery_queue.next,
- struct ptlrpc_request, rq_list);
-
- if (req->rq_reqmsg->transno != mds->mds_next_recovery_transno) {
- spin_unlock(&mds->mds_processing_task_lock);
- wait_event(mds->mds_next_transno_waitq,
- check_for_next_transno(mds));
- continue;
- }
- list_del(&req->rq_list);
- spin_unlock(&mds->mds_processing_task_lock);
-
- DEBUG_REQ(D_HA, req, "");
- mds_handle(req);
-
- if (list_empty(&mds->mds_recovery_queue))
- break;
- }
-}
-
-static int queue_recovery_request(struct ptlrpc_request *req,
- struct mds_obd *mds)
-{
- struct list_head *tmp;
- int inserted = 0, transno = req->rq_reqmsg->transno;
-
- if (!transno) {
- DEBUG_REQ(D_HA, req, "not queueing");
- return 1;
- }
-
- spin_lock(&mds->mds_processing_task_lock);
-
- if (mds->mds_processing_task == current->pid) {
- /* Processing the queue right now, don't re-add. */
- spin_unlock(&mds->mds_processing_task_lock);
- return 1;
- }
-
- /* XXX O(n^2) */
- list_for_each(tmp, &mds->mds_recovery_queue) {
- struct ptlrpc_request *reqiter =
- list_entry(tmp, struct ptlrpc_request, rq_list);
- if (reqiter->rq_reqmsg->transno > transno) {
- list_add_tail(&req->rq_list, &reqiter->rq_list);
- inserted = 1;
- break;
- }
- }
-
- if (!inserted)
- list_add_tail(&req->rq_list, &mds->mds_recovery_queue);
-
- if (mds->mds_processing_task != 0) {
- /* Someone else is processing this queue, we'll leave it to
- * them.
- */
- spin_unlock(&mds->mds_processing_task_lock);
- if (transno == mds->mds_next_recovery_transno)
- wake_up(&mds->mds_next_transno_waitq);
- return 0;
- }
-
- /* Nobody is processing, and we know there's (at least) one to process
- * now, so we'll do the honours.
- */
- mds->mds_processing_task = current->pid;
- spin_unlock(&mds->mds_processing_task_lock);
-
- process_recovery_queue(mds);
- return 0;
-}
-
-static int filter_recovery_request(struct ptlrpc_request *req,
- struct mds_obd *mds, int *process)
-{
- switch (req->rq_reqmsg->opc) {
- case MDS_CONNECT:
- case MDS_DISCONNECT:
- case MDS_OPEN:
- *process = 1;
- RETURN(0);
-
- case MDS_GETSTATUS: /* used in unmounting */
- case MDS_REINT:
- case LDLM_ENQUEUE:
- *process = queue_recovery_request(req, mds);
- RETURN(0);
-
- default:
- DEBUG_REQ(D_ERROR, req, "not permitted during recovery");
- *process = 0;
- RETURN(ptlrpc_error(req->rq_svc, req));
- }
-}
-
-static int mds_queue_final_reply(struct ptlrpc_request *req, int rc)
-{
- struct mds_obd *mds = mds_req2mds(req);
-
- if (rc) {
- /* Just like ptlrpc_error, but without the sending. */
- lustre_pack_msg(0, NULL, NULL, &req->rq_replen,
- &req->rq_repmsg);
- req->rq_type = PTL_RPC_MSG_ERR;
- }
-
- list_add(&req->rq_list, &mds->mds_delayed_reply_queue);
- if (--mds->mds_recoverable_clients == 0) {
- struct list_head *tmp, *n;
-
- CDEBUG(D_HA,
- "all clients recovered, sending delayed replies\n");
- list_for_each_safe(tmp, n, &mds->mds_delayed_reply_queue) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
- DEBUG_REQ(D_HA, req, "delayed:");
- ptlrpc_reply(req->rq_svc, req);
- }
- } else {
- CDEBUG(D_HA, "%d recoverable clients remain\n",
- mds->mds_recoverable_clients);
- }
-
- return 1;
-}
-
-static char *reint_names[] = {
- [REINT_SETATTR] "setattr",
- [REINT_CREATE] "create",
- [REINT_LINK] "link",
- [REINT_UNLINK] "unlink",
- [REINT_RENAME] "rename"
-};
-
-int mds_handle(struct ptlrpc_request *req)
-{
- int rc;
- int should_process;
- struct mds_obd *mds = NULL; /* quell gcc overwarning */
- ENTRY;
-
- rc = lustre_unpack_msg(req->rq_reqmsg, req->rq_reqlen);
- if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_HANDLE_UNPACK)) {
- CERROR("lustre_mds: Invalid request\n");
- GOTO(out, rc);
- }
-
- LASSERT(!strcmp(req->rq_obd->obd_type->typ_name, LUSTRE_MDT_NAME));
-
- if (req->rq_reqmsg->opc != MDS_CONNECT) {
- if (req->rq_export == NULL)
- GOTO(out, rc = -ENOTCONN);
-
- mds = mds_req2mds(req);
- if (mds->mds_recoverable_clients != 0) {
- rc = filter_recovery_request(req, mds, &should_process);
- if (rc || !should_process)
- RETURN(rc);
- }
- }
-
- switch (req->rq_reqmsg->opc) {
- case MDS_CONNECT:
- DEBUG_REQ(D_INODE, req, "connect");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_CONNECT_NET, 0);
- rc = target_handle_connect(req);
- /* Make sure that last_rcvd is correct. */
- if (!rc) {
- /* Now that we have an export, set mds. */
- mds = mds_req2mds(req);
- mds_fsync_super(mds->mds_sb);
- }
- break;
-
- case MDS_DISCONNECT:
- DEBUG_REQ(D_INODE, req, "disconnect");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_DISCONNECT_NET, 0);
- rc = target_handle_disconnect(req);
- /* Make sure that last_rcvd is correct. */
- if (!rc)
- mds_fsync_super(mds->mds_sb);
- goto out;
-
- case MDS_GETSTATUS:
- DEBUG_REQ(D_INODE, req, "getstatus");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_GETSTATUS_NET, 0);
- rc = mds_getstatus(req);
- break;
-
- case MDS_GETLOVINFO:
- DEBUG_REQ(D_INODE, req, "getlovinfo");
- rc = mds_getlovinfo(req);
- break;
-
- case MDS_GETATTR:
- DEBUG_REQ(D_INODE, req, "getattr");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_GETATTR_NET, 0);
- rc = mds_getattr(0, req);
- break;
-
- case MDS_STATFS:
- DEBUG_REQ(D_INODE, req, "statfs");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_STATFS_NET, 0);
- rc = mds_statfs(req);
- break;
-
- case MDS_READPAGE:
- DEBUG_REQ(D_INODE, req, "readpage\n");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_READPAGE_NET, 0);
- rc = mds_readpage(req);
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_SENDPAGE))
- return 0;
- break;
-
- case MDS_REINT: {
- int size = sizeof(struct mds_body);
- int opc = *(u32 *)lustre_msg_buf(req->rq_reqmsg, 0),
- realopc = opc & REINT_OPCODE_MASK;
-
- DEBUG_REQ(D_INODE, req, "reint (%s%s)",
- reint_names[realopc],
- opc & REINT_REPLAYING ? "|REPLAYING" : "");
-
- OBD_FAIL_RETURN(OBD_FAIL_MDS_REINT_NET, 0);
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen,
- &req->rq_repmsg);
- if (rc) {
- req->rq_status = rc;
- break;
- }
- rc = mds_reint(req, 0);
- OBD_FAIL_RETURN(OBD_FAIL_MDS_REINT_NET_REP, 0);
- break;
- }
-
- case MDS_OPEN:
- DEBUG_REQ(D_INODE, req, "open");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_OPEN_NET, 0);
- rc = mds_open(req);
- break;
-
- case MDS_CLOSE:
- DEBUG_REQ(D_INODE, req, "close");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_CLOSE_NET, 0);
- rc = mds_close(req);
- break;
-
- case LDLM_ENQUEUE:
- DEBUG_REQ(D_INODE, req, "enqueue");
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_ENQUEUE, 0);
- rc = ldlm_handle_enqueue(req);
- break;
- case LDLM_CONVERT:
- DEBUG_REQ(D_INODE, req, "convert");
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_CONVERT, 0);
- rc = ldlm_handle_convert(req);
- break;
- case LDLM_BL_CALLBACK:
- case LDLM_CP_CALLBACK:
- DEBUG_REQ(D_INODE, req, "callback");
- CERROR("callbacks should not happen on MDS\n");
- LBUG();
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_BL_CALLBACK, 0);
- break;
- default:
- rc = ptlrpc_error(req->rq_svc, req);
- RETURN(rc);
- }
-
- EXIT;
-
- if (!rc) {
- struct mds_export_data *med = &req->rq_export->exp_mds_data;
-
- req->rq_repmsg->last_xid =
- HTON__u64(le64_to_cpu(med->med_mcd->mcd_last_xid));
- req->rq_repmsg->last_committed =
- HTON__u64(mds->mds_last_committed);
- CDEBUG(D_INFO, "last_rcvd ~%Lu, last_committed %Lu, xid %d\n",
- (unsigned long long)mds->mds_last_rcvd,
- (unsigned long long)mds->mds_last_committed,
- cpu_to_le32(req->rq_xid));
- }
- out:
-
- if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_LAST_REPLAY) {
- struct mds_obd *mds = mds_req2mds(req);
- LASSERT(mds->mds_recoverable_clients);
- DEBUG_REQ(D_HA, req, "LAST_REPLAY, queuing reply");
- return mds_queue_final_reply(req, rc);
- }
-
- /* MDS_CONNECT / EALREADY (note: not -EALREADY!) isn't an error */
- if (rc && (req->rq_reqmsg->opc != MDS_CONNECT ||
- rc != EALREADY)) {
- CERROR("mds: processing error (opcode %d): %d\n",
- req->rq_reqmsg->opc, rc);
- ptlrpc_error(req->rq_svc, req);
- } else {
- CDEBUG(D_NET, "sending reply\n");
- ptlrpc_reply(req->rq_svc, req);
- }
- return 0;
-}
-
-/* Update the server data on disk. This stores the new mount_count and
- * also the last_rcvd value to disk. If we don't have a clean shutdown,
- * then the server last_rcvd value may be less than that of the clients.
- * This will alert us that we may need to do client recovery.
- *
- * Assumes we are already in the server filesystem context.
- *
- * Also assumes for mds_last_rcvd that we are not modifying it (no locking).
- */
-int mds_update_server_data(struct mds_obd *mds)
-{
- struct mds_server_data *msd = mds->mds_server_data;
- struct file *filp = mds->mds_rcvd_filp;
- loff_t off = 0;
- int rc;
-
- msd->msd_last_rcvd = cpu_to_le64(mds->mds_last_rcvd);
- msd->msd_mount_count = cpu_to_le64(mds->mds_mount_count);
-
- CDEBUG(D_SUPER, "MDS mount_count is %Lu, last_rcvd is %Lu\n",
- (unsigned long long)mds->mds_mount_count,
- (unsigned long long)mds->mds_last_rcvd);
- rc = lustre_fwrite(filp, (char *)msd, sizeof(*msd), &off);
- if (rc != sizeof(*msd)) {
- CERROR("error writing MDS server data: rc = %d\n", rc);
- if (rc > 0)
- RETURN(-EIO);
- RETURN(rc);
- }
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- rc = fsync_dev(filp->f_dentry->d_inode->i_rdev);
-#else
- rc = file_fsync(filp, filp->f_dentry, 1);
-#endif
- if (rc)
- CERROR("error flushing MDS server data: rc = %d\n", rc);
-
- return 0;
-}
-
-/* Do recovery actions for the MDS */
-static int mds_recovery_complete(struct obd_device *obddev)
-{
- struct mds_obd *mds = &obddev->u.mds;
- struct obd_run_ctxt saved;
- int rc;
-
- LASSERT(mds->mds_recoverable_clients == 0);
-
- /* This happens at the end when recovery is complete */
- ++mds->mds_mount_count;
- push_ctxt(&saved, &mds->mds_ctxt, NULL);
- rc = mds_update_server_data(mds);
- pop_ctxt(&saved, &mds->mds_ctxt, NULL);
-
- return rc;
-}
-
-/* mount the file system (secretly) */
-static int mds_setup(struct obd_device *obddev, obd_count len, void *buf)
-{
- struct obd_ioctl_data* data = buf;
- struct mds_obd *mds = &obddev->u.mds;
- struct vfsmount *mnt;
- int rc = 0;
- ENTRY;
-
- MOD_INC_USE_COUNT;
-#ifdef CONFIG_DEV_RDONLY
- dev_clear_rdonly(2);
-#endif
- if (!data->ioc_inlbuf1 || !data->ioc_inlbuf2)
- GOTO(err_dec, rc = -EINVAL);
-
- mds->mds_fstype = strdup(data->ioc_inlbuf2);
-
- mnt = do_kern_mount(mds->mds_fstype, 0, data->ioc_inlbuf1, NULL);
- if (IS_ERR(mnt)) {
- rc = PTR_ERR(mnt);
- CERROR("do_kern_mount failed: rc = %d\n", rc);
- GOTO(err_kfree, rc);
- }
-
- CERROR("%s: mnt is %p\n", data->ioc_inlbuf1, mnt);
- mds->mds_sb = mnt->mnt_root->d_inode->i_sb;
- if (!mds->mds_sb)
- GOTO(err_put, rc = -ENODEV);
-
- init_MUTEX(&mds->mds_transno_sem);
- mds->mds_max_mdsize = sizeof(struct lov_mds_md);
- rc = mds_fs_setup(obddev, mnt);
- if (rc) {
- CERROR("MDS filesystem method init failed: rc = %d\n", rc);
- GOTO(err_put, rc);
- }
-
- obddev->obd_namespace =
- ldlm_namespace_new("mds_server", LDLM_NAMESPACE_SERVER);
- if (obddev->obd_namespace == NULL) {
- mds_cleanup(obddev);
- GOTO(err_fs, rc = -ENOMEM);
- }
-
- ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
- "mds_ldlm_client", &obddev->obd_ldlm_client);
-
- spin_lock_init(&mds->mds_processing_task_lock);
- mds->mds_processing_task = 0;
- INIT_LIST_HEAD(&mds->mds_recovery_queue);
- INIT_LIST_HEAD(&mds->mds_delayed_reply_queue);
-
- RETURN(0);
-
-err_fs:
- mds_fs_cleanup(obddev);
-err_put:
- unlock_kernel();
- mntput(mds->mds_vfsmnt);
- mds->mds_sb = 0;
- lock_kernel();
-err_kfree:
- kfree(mds->mds_fstype);
-err_dec:
- MOD_DEC_USE_COUNT;
- RETURN(rc);
-}
-
-static int mds_cleanup(struct obd_device *obddev)
-{
- struct super_block *sb;
- struct mds_obd *mds = &obddev->u.mds;
- struct obd_run_ctxt saved;
- ENTRY;
-
- sb = mds->mds_sb;
- if (!mds->mds_sb)
- RETURN(0);
-
- push_ctxt(&saved, &mds->mds_ctxt, NULL);
- mds_update_server_data(mds);
-
- if (mds->mds_rcvd_filp) {
- int rc = filp_close(mds->mds_rcvd_filp, 0);
- mds->mds_rcvd_filp = NULL;
-
- if (rc)
- CERROR("last_rcvd file won't close, rc=%d\n", rc);
- }
- pop_ctxt(&saved, &mds->mds_ctxt, NULL);
-
- unlock_kernel();
- mntput(mds->mds_vfsmnt);
- mds->mds_sb = 0;
- kfree(mds->mds_fstype);
-
- ldlm_namespace_free(obddev->obd_namespace);
-
- lock_kernel();
-#ifdef CONFIG_DEV_RDONLY
- dev_clear_rdonly(2);
-#endif
- mds_fs_cleanup(obddev);
-
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-static int ldlm_intent_policy(struct ldlm_lock *lock, void *req_cookie,
- ldlm_mode_t mode, int flags, void *data)
-{
- struct ptlrpc_request *req = req_cookie;
- int rc = 0;
- ENTRY;
-
- if (!req_cookie)
- RETURN(0);
-
- if (req->rq_reqmsg->bufcount > 1) {
- /* an intent needs to be considered */
- struct ldlm_intent *it = lustre_msg_buf(req->rq_reqmsg, 1);
- struct mds_obd *mds= &req->rq_export->exp_obd->u.mds;
- struct mds_body *mds_rep;
- struct ldlm_reply *rep;
- __u64 new_resid[3] = {0, 0, 0}, old_res;
- int rc, size[3] = {sizeof(struct ldlm_reply),
- sizeof(struct mds_body),
- mds->mds_max_mdsize};
-
- it->opc = NTOH__u64(it->opc);
-
- LDLM_DEBUG(lock, "intent policy, opc: %s",
- ldlm_it2str(it->opc));
-
- rc = lustre_pack_msg(3, size, NULL, &req->rq_replen,
- &req->rq_repmsg);
- if (rc) {
- rc = req->rq_status = -ENOMEM;
- RETURN(rc);
- }
-
- rep = lustre_msg_buf(req->rq_repmsg, 0);
- rep->lock_policy_res1 = 1;
-
- /* execute policy */
- switch ((long)it->opc) {
- case IT_CREAT|IT_OPEN:
- rc = mds_reint(req, 2);
- if (rc || (req->rq_status != 0 &&
- req->rq_status != -EEXIST)) {
- rep->lock_policy_res2 = req->rq_status;
- RETURN(ELDLM_LOCK_ABORTED);
- }
- break;
- case IT_CREAT:
- case IT_MKDIR:
- case IT_MKNOD:
- case IT_RENAME2:
- case IT_LINK2:
- case IT_RMDIR:
- case IT_SYMLINK:
- case IT_UNLINK:
- rc = mds_reint(req, 2);
- if (rc || (req->rq_status != 0 &&
- req->rq_status != -EISDIR &&
- req->rq_status != -ENOTDIR)) {
- rep->lock_policy_res2 = req->rq_status;
- RETURN(ELDLM_LOCK_ABORTED);
- }
- break;
- case IT_GETATTR:
- case IT_LOOKUP:
- case IT_OPEN:
- case IT_READDIR:
- case IT_READLINK:
- case IT_RENAME:
- case IT_LINK:
- case IT_SETATTR:
- rc = mds_getattr_name(2, req);
- /* FIXME: we need to sit down and decide on who should
- * set req->rq_status, who should return negative and
- * positive return values, and what they all mean. */
- if (rc || req->rq_status != 0) {
- rep->lock_policy_res2 = req->rq_status;
- RETURN(ELDLM_LOCK_ABORTED);
- }
- break;
- case IT_READDIR|IT_OPEN:
- LBUG();
- break;
- default:
- CERROR("Unhandled intent "LPD64"\n", it->opc);
- LBUG();
- }
-
- /* We don't bother returning a lock to the client for a file
- * or directory we are removing.
- *
- * As for link and rename, there is no reason for the client
- * to get a lock on the target at this point. If they are
- * going to modify the file/directory later they will get a
- * lock at that time.
- */
- if (it->opc & (IT_UNLINK | IT_RMDIR | IT_LINK | IT_LINK2 |
- IT_RENAME | IT_RENAME2))
- RETURN(ELDLM_LOCK_ABORTED);
-
- rep->lock_policy_res2 = req->rq_status;
- mds_rep = lustre_msg_buf(req->rq_repmsg, 1);
-
- /* If the client is about to open a file that doesn't have an MD
- * stripe record, it's going to need a write lock. */
- if (it->opc & IT_OPEN && !(mds_rep->valid & OBD_MD_FLEASIZE)) {
- LDLM_DEBUG(lock, "open with no EA; returning PW lock");
- lock->l_req_mode = LCK_PW;
- }
-
- if (flags & LDLM_FL_INTENT_ONLY) {
- LDLM_DEBUG(lock, "INTENT_ONLY, aborting lock");
- RETURN(ELDLM_LOCK_ABORTED);
- }
- /* Give the client a lock on the child object, instead of the
- * parent that it requested. */
- new_resid[0] = NTOH__u32(mds_rep->ino);
- new_resid[1] = NTOH__u32(mds_rep->generation);
- if (new_resid[0] == 0)
- LBUG();
- old_res = lock->l_resource->lr_name[0];
-
- ldlm_lock_change_resource(lock, new_resid);
- if (lock->l_resource == NULL) {
- LBUG();
- RETURN(-ENOMEM);
- }
- LDLM_DEBUG(lock, "intent policy, old res %ld",
- (long)old_res);
- RETURN(ELDLM_LOCK_CHANGED);
- } else {
- int size = sizeof(struct ldlm_reply);
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen,
- &req->rq_repmsg);
- if (rc) {
- LBUG();
- RETURN(-ENOMEM);
- }
- }
- RETURN(rc);
-}
-
-int mds_attach(struct obd_device *dev, obd_count len, void *data)
-{
- return lprocfs_reg_obd(dev, status_var_nm_1, dev);
-}
-
-int mds_detach(struct obd_device *dev)
-{
- return lprocfs_dereg_obd(dev);
-}
-
-static int mdt_setup(struct obd_device *obddev, obd_count len, void *buf)
-{
- int i;
- // struct obd_ioctl_data* data = buf;
- struct mds_obd *mds = &obddev->u.mds;
- int rc = 0;
- ENTRY;
-
- MOD_INC_USE_COUNT;
-
- mds->mds_service = ptlrpc_init_svc(MDS_NEVENTS, MDS_NBUFS,
- MDS_BUFSIZE, MDS_MAXREQSIZE,
- MDS_REQUEST_PORTAL, MDC_REPLY_PORTAL,
- "self", mds_handle, "mds");
- if (!mds->mds_service) {
- CERROR("failed to start service\n");
- GOTO(err_dec, rc = -ENOMEM);
- }
-
- for (i = 0; i < MDT_NUM_THREADS; i++) {
- char name[32];
- sprintf(name, "ll_mdt_%02d", i);
- rc = ptlrpc_start_thread(obddev, mds->mds_service, name);
- if (rc) {
- CERROR("cannot start MDT thread #%d: rc %d\n", i, rc);
- GOTO(err_thread, rc);
- }
- }
-
- RETURN(0);
-
-err_thread:
- ptlrpc_stop_all_threads(mds->mds_service);
- ptlrpc_unregister_service(mds->mds_service);
-err_dec:
- MOD_DEC_USE_COUNT;
- RETURN(rc);
-}
-
-
-static int mdt_cleanup(struct obd_device *obddev)
-{
- struct mds_obd *mds = &obddev->u.mds;
- ENTRY;
-
- ptlrpc_stop_all_threads(mds->mds_service);
- ptlrpc_unregister_service(mds->mds_service);
-
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-extern int mds_iocontrol(unsigned int cmd, struct lustre_handle *conn,
- int len, void *karg, void *uarg);
-
-/* use obd ops to offer management infrastructure */
-static struct obd_ops mds_obd_ops = {
- o_attach: mds_attach,
- o_detach: mds_detach,
- o_connect: mds_connect,
- o_disconnect: mds_disconnect,
- o_setup: mds_setup,
- o_cleanup: mds_cleanup,
- o_iocontrol: mds_iocontrol
-};
-
-static struct obd_ops mdt_obd_ops = {
- o_setup: mdt_setup,
- o_cleanup: mdt_cleanup,
-};
-
-
-static int __init mds_init(void)
-{
-
- mds_file_cache = kmem_cache_create("ll_mds_file_data",
- sizeof(struct mds_file_data),
- 0, 0, NULL, NULL);
- if (mds_file_cache == NULL)
- return -ENOMEM;
-
- class_register_type(&mds_obd_ops, status_class_var, LUSTRE_MDS_NAME);
- class_register_type(&mdt_obd_ops, 0, LUSTRE_MDT_NAME);
- ldlm_register_intent(ldlm_intent_policy);
- return 0;
-
-}
-
-static void __exit mds_exit(void)
-{
-
-
- ldlm_unregister_intent();
- class_unregister_type(LUSTRE_MDS_NAME);
- class_unregister_type(LUSTRE_MDT_NAME);
- if (kmem_cache_destroy(mds_file_cache))
- CERROR("couldn't free MDS file cache\n");
-
-}
-
-MODULE_AUTHOR("Cluster File Systems <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Metadata Server (MDS) v0.01");
-MODULE_LICENSE("GPL");
-
-module_init(mds_init);
-module_exit(mds_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-int rd_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- int len = 0;
- len += snprintf(page, count, "%s\n", temp->obd_uuid);
- return len;
-}
-int rd_blksize(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct mds_obd *mds = &temp->u.mds;
- struct statfs mystats;
- int rc, len = 0;
-
- rc = vfs_statfs(mds->mds_sb, &mystats);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- return 0;
- }
- len += snprintf(page, count, LPU64"\n", (__u64)(mystats.f_bsize));
- return len;
-
-}
-int rd_kbtotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct mds_obd *mds = &temp->u.mds;
- struct statfs mystats;
- int rc, len = 0;
- __u32 blk_size;
- __u64 result;
-
- rc = vfs_statfs(mds->mds_sb, &mystats);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- return 0;
- }
-
- blk_size = mystats.f_bsize;
- blk_size >>= 10;
- result = mystats.f_blocks;
- while(blk_size >>= 1){
- result <<= 1;
- }
- len += snprintf(page, count, LPU64"\n", result);
- return len;
-
-}
-
-int rd_kbfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct mds_obd *mds = &temp->u.mds;
- struct statfs mystats;
- int rc, len = 0;
- __u32 blk_size;
- __u64 result;
-
-
- rc = vfs_statfs(mds->mds_sb, &mystats);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- return 0;
- }
- blk_size = mystats.f_bsize;
- blk_size >>= 10;
- result = mystats.f_blocks;
- while(blk_size >>= 1){
- result <<= 1;
- }
- len += snprintf(page, count, LPU64"\n", result);
- return len;
-
-}
-
-int rd_fstype(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct mds_obd *mds = &temp->u.mds;
- int len = 0;
- len += snprintf(page, count, "%s\n", mds->mds_fstype);
- return len;
-
-}
-
-int rd_filestotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct mds_obd *mds = &temp->u.mds;
- struct statfs mystats;
- int rc, len = 0;
-
- rc = vfs_statfs(mds->mds_sb, &mystats);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- return 0;
- }
-
- len += snprintf(page, count, LPU64"\n", (__u64)(mystats.f_files));
- return len;
-
-
-}
-
-int rd_filesfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct mds_obd *mds = &temp->u.mds;
- struct statfs mystats;
- int rc, len = 0;
-
- rc = vfs_statfs(mds->mds_sb, &mystats);
- if (rc) {
- CERROR("mds: statfs failed: rc %d\n", rc);
- return 0;
- }
-
- len += snprintf(page, count, LPU64"\n", (__u64)(mystats.f_ffree));
- return len;
-}
-
-int rd_filegroups(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-struct lprocfs_vars status_var_nm_1[]={
- {"status/uuid", rd_uuid, 0, 0},
- {"status/blocksize",rd_blksize, 0, 0},
- {"status/kbytestotal",rd_kbtotal, 0, 0},
- {"status/kbytesfree", rd_kbfree, 0, 0},
- {"status/fstype", rd_fstype, 0, 0},
- {"status/filestotal", rd_filestotal, 0, 0},
- {"status/filesfree", rd_filesfree, 0, 0},
- {"status/filegroups", rd_filegroups, 0, 0},
- {0}
-};
-int rd_numrefs(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_type* class = (struct obd_type*)data;
- int len = 0;
- len += snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-struct lprocfs_vars status_class_var[]={
- {"status/num_refs", rd_numrefs, 0, 0},
- {0}
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * linux/mds/mds_null.c
- *
- * Lustre Metadata Server (mds) journal abstraction routines
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * author: Andreas Dilger <adilger@clusterfs.com>
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- */
-
-#define DEBUG_SUBSYSTEM S_MDS
-
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/lustre_mds.h>
-#include <linux/module.h>
-
-static void *mds_ext2_start(struct inode *inode, int nblocks)
-{
- return (void *)1;
-}
-
-static int mds_ext2_stop(struct inode *inode, void *handle)
-{
- return 0;
-}
-
-static int mds_ext2_setattr(struct dentry *dentry, void *handle,
- struct iattr *iattr)
-{
- struct inode *inode = dentry->d_inode;
-
- lock_kernel();
-
- /* a _really_ horrible hack to avoid removing the data stored
- in the block pointers; this data is the object id
- this will go into an extended attribute at some point.
- */
- if (iattr->ia_valid & ATTR_SIZE) {
- /* ATTR_SIZE would invoke truncate: clear it */
- iattr->ia_valid &= ~ATTR_SIZE;
- inode->i_size = iattr->ia_size;
-
- /* make sure _something_ gets set - so new inode
- goes to disk (probably won't work over XFS */
- if (!iattr->ia_valid & ATTR_MODE) {
- iattr->ia_valid |= ATTR_MODE;
- iattr->ia_mode = inode->i_mode;
- }
- }
-
- if (inode->i_op->setattr)
- rc = inode->i_op->setattr(dentry, iattr);
- else
- rc = inode_setattr(inode, iattr);
-
- unlock_kernel();
-
- return rc;
-}
-
-/*
- * FIXME: nasty hack - store the object id in the first two
- * direct block spots. This should be done with EAs...
- */
-static int mds_ext2_set_objid(struct inode *inode, void *handle, obd_id id)
-{
- (__u64)(inode->u.ext2_i.i_data[0]) = cpu_to_le64(id);
- return 0;
-}
-
-static int mds_ext2_get_objid(struct inode *inode, obd_id *id)
-{
- *id = le64_to_cpu(inode->u.ext2_i.i_data[0]);
-
- return 0;
-}
-
-static ssize_t mds_ext2_readpage(struct file *file, char *buf, size_t count,
- loff_t *offset)
-{
- if (S_ISREG(file->f_dentry->d_inode->i_mode))
- return file->f_op->read(file, buf, count, offset);
- else
- return generic_file_read(file, buf, count, offset);
-}
-
-static struct mds_fs_operations mds_ext2_fs_ops;
-
-static void mds_ext2_delete_inode(struct inode *inode)
-{
- if (S_ISREG(inode->i_mode))
- mds_ext2_set_objid(inode, NULL, 0);
-
- mds_ext2_fs_ops.cl_delete_inode(inode);
-}
-
-static int mds_ext2_set_last_rcvd(struct mds_obd *mds, void *handle)
-{
- /* Bail for ext2 - can't tell when it is on disk anyways, sync? */
- mds->mds_last_committed = mds->mds_last_rcvd;
-
- return 0;
-}
-
-static int mds_ext2_journal_data(struct file *filp)
-{
- return 0;
-}
-
-static struct mds_fs_operations mds_ext2_fs_ops = {
- fs_owner: THIS_MODULE,
- fs_start: mds_ext2_start,
- fs_commit: mds_ext2_stop,
- fs_setattr: mds_ext2_setattr,
- fs_set_objid: mds_ext2_set_objid,
- fs_get_objid: mds_ext2_get_objid,
- fs_readpage: mds_ext2_readpage,
- fs_delete_inode: mds_ext2_delete_inode,
- cl_delete_inode: clear_inode,
- fs_journal_data: mds_ext2_journal_data,
- fs_set_last_rcvd: mds_ext2_set_last_rcvd,
-};
-
-static int __init mds_ext2_init(void)
-{
- return mds_register_fs_type(&mds_ext2_fs_ops, "ext2");
-}
-
-static void __exit mds_ext2_exit(void)
-{
- mds_unregister_fs_type("ext2");
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <adilger@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre MDS ext2 Filesystem Helper v0.1");
-MODULE_LICENSE("GPL");
-
-module_init(mds_ext2_init);
-module_exit(mds_ext2_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * lustre/mds/mds_ext3.c
- * Lustre Metadata Server (mds) journal abstraction routines
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * Author: Andreas Dilger <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_MDS
-
-#include <linux/fs.h>
-#include <linux/jbd.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/ext3_fs.h>
-#include <linux/ext3_jbd.h>
-#include <../fs/ext3/xattr.h>
-#include <linux/kp30.h>
-#include <linux/lustre_mds.h>
-#include <linux/obd.h>
-#include <linux/module.h>
-
-static struct mds_fs_operations mds_ext3_fs_ops;
-static kmem_cache_t *mcb_cache;
-static int mcb_cache_count;
-
-struct mds_cb_data {
- struct journal_callback cb_jcb;
- struct mds_obd *cb_mds;
- __u64 cb_last_rcvd;
-};
-
-#define EXT3_XATTR_INDEX_LUSTRE 5
-#define XATTR_LUSTRE_MDS_OBJID "system.lustre_mds_objid"
-
-/*
- * We don't currently need any additional blocks for rmdir and
- * unlink transactions because we are storing the OST oa_id inside
- * the inode (which we will be changing anyways as part of this
- * transaction).
- */
-static void *mds_ext3_start(struct inode *inode, int op)
-{
- /* For updates to the last recieved file */
- int nblocks = EXT3_DATA_TRANS_BLOCKS;
- void *handle;
-
- switch(op) {
- case MDS_FSOP_RMDIR:
- case MDS_FSOP_UNLINK:
- nblocks += EXT3_DELETE_TRANS_BLOCKS;
- break;
- case MDS_FSOP_RENAME:
- /* We may be modifying two directories */
- nblocks += EXT3_DATA_TRANS_BLOCKS;
- case MDS_FSOP_SYMLINK:
- /* Possible new block + block bitmap + GDT for long symlink */
- nblocks += 3;
- case MDS_FSOP_CREATE:
- case MDS_FSOP_MKDIR:
- case MDS_FSOP_MKNOD:
- /* New inode + block bitmap + GDT for new file */
- nblocks += 3;
- case MDS_FSOP_LINK:
- /* Change parent directory */
- nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS+EXT3_DATA_TRANS_BLOCKS;
- break;
- case MDS_FSOP_SETATTR:
- /* Setattr on inode */
- nblocks += 1;
- break;
- default: CERROR("unknown transaction start op %d\n", op);
- LBUG();
- }
-
- lock_kernel();
- handle = journal_start(EXT3_JOURNAL(inode), nblocks);
- unlock_kernel();
-
- return handle;
-}
-
-static int mds_ext3_commit(struct inode *inode, void *handle)
-{
- int rc;
-
- lock_kernel();
- rc = journal_stop((handle_t *)handle);
- unlock_kernel();
-
- return rc;
-}
-
-static int mds_ext3_setattr(struct dentry *dentry, void *handle,
- struct iattr *iattr)
-{
- struct inode *inode = dentry->d_inode;
- int rc;
-
- lock_kernel();
- if (inode->i_op->setattr)
- rc = inode->i_op->setattr(dentry, iattr);
- else
- rc = inode_setattr(inode, iattr);
-
- unlock_kernel();
-
- return rc;
-}
-
-static int mds_ext3_set_md(struct inode *inode, void *handle,
- struct lov_mds_md *lmm, int lmm_size)
-{
- int rc;
-
- down(&inode->i_sem);
- lock_kernel();
- rc = ext3_xattr_set(handle, inode, EXT3_XATTR_INDEX_LUSTRE,
- XATTR_LUSTRE_MDS_OBJID, lmm, lmm_size, 0);
- unlock_kernel();
- up(&inode->i_sem);
-
- if (rc) {
- CERROR("error adding objectid "LPX64" to inode %ld: %d\n",
- lmm->lmm_object_id, inode->i_ino, rc);
- if (rc != -ENOSPC) LBUG();
- }
- return rc;
-}
-
-static int mds_ext3_get_md(struct inode *inode, struct lov_mds_md *lmm,int size)
-{
- int rc;
-
- down(&inode->i_sem);
- lock_kernel();
- rc = ext3_xattr_get(inode, EXT3_XATTR_INDEX_LUSTRE,
- XATTR_LUSTRE_MDS_OBJID, lmm, size);
- unlock_kernel();
- up(&inode->i_sem);
-
- /* This gives us the MD size */
- if (lmm == NULL)
- return (rc == -ENODATA) ? 0 : rc;
-
- if (rc < 0) {
- CDEBUG(D_INFO, "error getting EA %s from MDS inode %ld: "
- "rc = %d\n", XATTR_LUSTRE_MDS_OBJID, inode->i_ino, rc);
- memset(lmm, 0, size);
- return (rc == -ENODATA) ? 0 : rc;
- }
-
- /* This field is byteswapped because it appears in the
- * catalogue. All others are opaque to the MDS */
- lmm->lmm_object_id = le64_to_cpu(lmm->lmm_object_id);
-
- return rc;
-}
-
-static ssize_t mds_ext3_readpage(struct file *file, char *buf, size_t count,
- loff_t *offset)
-{
- struct inode *inode = file->f_dentry->d_inode;
- int rc = 0;
-
- if (S_ISREG(inode->i_mode))
- rc = file->f_op->read(file, buf, count, offset);
- else {
- struct buffer_head *bh;
-
- /* FIXME: this assumes the blocksize == count, but the calling
- * function will detect this as an error for now */
- bh = ext3_bread(NULL, inode,
- *offset >> inode->i_sb->s_blocksize_bits,
- 0, &rc);
-
- if (bh) {
- memcpy(buf, bh->b_data, inode->i_blksize);
- brelse(bh);
- rc = inode->i_blksize;
- }
- }
-
- return rc;
-}
-
-static void mds_ext3_delete_inode(struct inode *inode)
-{
- if (S_ISREG(inode->i_mode)) {
- void *handle = mds_ext3_start(inode, MDS_FSOP_UNLINK);
-
- if (IS_ERR(handle)) {
- CERROR("unable to start transaction");
- EXIT;
- return;
- }
- if (mds_ext3_set_md(inode, handle, NULL, 0))
- CERROR("error clearing objid on %ld\n", inode->i_ino);
-
- if (mds_ext3_fs_ops.cl_delete_inode)
- mds_ext3_fs_ops.cl_delete_inode(inode);
-
- if (mds_ext3_commit(inode, handle))
- CERROR("error closing handle on %ld\n", inode->i_ino);
- } else
- mds_ext3_fs_ops.cl_delete_inode(inode);
-}
-
-static void mds_ext3_callback_status(struct journal_callback *jcb, int error)
-{
- struct mds_cb_data *mcb = (struct mds_cb_data *)jcb;
-
- CDEBUG(D_EXT2, "got callback for last_rcvd "LPD64": rc = %d\n",
- mcb->cb_last_rcvd, error);
- if (!error && mcb->cb_last_rcvd > mcb->cb_mds->mds_last_committed)
- mcb->cb_mds->mds_last_committed = mcb->cb_last_rcvd;
-
- kmem_cache_free(mcb_cache, mcb);
- --mcb_cache_count;
-}
-
-static int mds_ext3_set_last_rcvd(struct mds_obd *mds, void *handle)
-{
- struct mds_cb_data *mcb;
-
- mcb = kmem_cache_alloc(mcb_cache, GFP_NOFS);
- if (!mcb)
- RETURN(-ENOMEM);
-
- ++mcb_cache_count;
- mcb->cb_mds = mds;
- mcb->cb_last_rcvd = mds->mds_last_rcvd;
-
-#ifdef HAVE_JOURNAL_CALLBACK_STATUS
- CDEBUG(D_EXT2, "set callback for last_rcvd: "LPD64"\n",
- mcb->cb_last_rcvd);
- lock_kernel();
- /* Note that an "incompatible pointer" warning here is OK for now */
- journal_callback_set(handle, mds_ext3_callback_status,
- (struct journal_callback *)mcb);
- unlock_kernel();
-#else
-#warning "no journal callback kernel patch, faking it..."
- {
- static long next = 0;
-
- if (time_after(jiffies, next)) {
- CERROR("no journal callback kernel patch, faking it...\n");
- next = jiffies + 300 * HZ;
- }
-
- mds_ext3_callback_status((struct journal_callback *)mcb, 0);
-#endif
-
- return 0;
-}
-
-static int mds_ext3_journal_data(struct file *filp)
-{
- struct inode *inode = filp->f_dentry->d_inode;
-
- EXT3_I(inode)->i_flags |= EXT3_JOURNAL_DATA_FL;
-
- return 0;
-}
-
-/*
- * We need to hack the return value for the free inode counts because
- * the current EA code requires one filesystem block per inode with EAs,
- * so it is possible to run out of blocks before we run out of inodes.
- *
- * This can be removed when the ext3 EA code is fixed.
- */
-static int mds_ext3_statfs(struct super_block *sb, struct statfs *sfs)
-{
- int rc = vfs_statfs(sb, sfs);
-
- if (!rc && sfs->f_bfree < sfs->f_ffree)
- sfs->f_ffree = sfs->f_bfree;
-
- return rc;
-}
-
-static struct mds_fs_operations mds_ext3_fs_ops = {
- fs_owner: THIS_MODULE,
- fs_start: mds_ext3_start,
- fs_commit: mds_ext3_commit,
- fs_setattr: mds_ext3_setattr,
- fs_set_md: mds_ext3_set_md,
- fs_get_md: mds_ext3_get_md,
- fs_readpage: mds_ext3_readpage,
- fs_delete_inode: mds_ext3_delete_inode,
- cl_delete_inode: clear_inode,
- fs_journal_data: mds_ext3_journal_data,
- fs_set_last_rcvd: mds_ext3_set_last_rcvd,
- fs_statfs: mds_ext3_statfs,
-};
-
-static int __init mds_ext3_init(void)
-{
- int rc;
-
- //rc = ext3_xattr_register();
- mcb_cache = kmem_cache_create("mds_ext3_mcb",
- sizeof(struct mds_cb_data), 0,
- 0, NULL, NULL);
- if (!mcb_cache) {
- CERROR("error allocating MDS journal callback cache\n");
- GOTO(out, rc = -ENOMEM);
- }
-
- rc = mds_register_fs_type(&mds_ext3_fs_ops, "ext3");
-
- if (rc)
- kmem_cache_destroy(mcb_cache);
-out:
- return rc;
-}
-
-static void __exit mds_ext3_exit(void)
-{
- int rc;
-
- mds_unregister_fs_type("ext3");
- rc = kmem_cache_destroy(mcb_cache);
-
- if (rc || mcb_cache_count) {
- CERROR("can't free MDS callback cache: count %d, rc = %d\n",
- mcb_cache_count, rc);
- }
-
- //rc = ext3_xattr_unregister();
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre MDS ext3 Filesystem Helper v0.1");
-MODULE_LICENSE("GPL");
-
-module_init(mds_ext3_init);
-module_exit(mds_ext3_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * lustre/mds/mds_extN.c
- * Lustre Metadata Server (mds) journal abstraction routines
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * Author: Andreas Dilger <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define DEBUG_SUBSYSTEM S_MDS
-
-#include <linux/fs.h>
-#include <linux/jbd.h>
-#include <linux/slab.h>
-#include <linux/extN_fs.h>
-#include <linux/extN_jbd.h>
-#include <linux/extN_xattr.h>
-#include <linux/kp30.h>
-#include <linux/lustre_mds.h>
-#include <linux/obd.h>
-#include <linux/module.h>
-
-static struct mds_fs_operations mds_extN_fs_ops;
-static kmem_cache_t *mcb_cache;
-static int mcb_cache_count;
-
-struct mds_cb_data {
- struct journal_callback cb_jcb;
- struct mds_obd *cb_mds;
- __u64 cb_last_rcvd;
-};
-
-#define EXTN_XATTR_INDEX_LUSTRE 5
-#define XATTR_LUSTRE_MDS_OBJID "system.lustre_mds_objid"
-
-/*
- * We don't currently need any additional blocks for rmdir and
- * unlink transactions because we are storing the OST oa_id inside
- * the inode (which we will be changing anyways as part of this
- * transaction).
- */
-static void *mds_extN_start(struct inode *inode, int op)
-{
- /* For updates to the last recieved file */
- int nblocks = EXTN_DATA_TRANS_BLOCKS;
- void *handle;
-
- switch(op) {
- case MDS_FSOP_RMDIR:
- case MDS_FSOP_UNLINK:
- nblocks += EXTN_DELETE_TRANS_BLOCKS;
- break;
- case MDS_FSOP_RENAME:
- /* We may be modifying two directories */
- nblocks += EXTN_DATA_TRANS_BLOCKS;
- case MDS_FSOP_SYMLINK:
- /* Possible new block + block bitmap + GDT for long symlink */
- nblocks += 3;
- case MDS_FSOP_CREATE:
- case MDS_FSOP_MKDIR:
- case MDS_FSOP_MKNOD:
- /* New inode + block bitmap + GDT for new file */
- nblocks += 3;
- case MDS_FSOP_LINK:
- /* Change parent directory */
- nblocks += EXTN_INDEX_EXTRA_TRANS_BLOCKS+EXTN_DATA_TRANS_BLOCKS;
- break;
- case MDS_FSOP_SETATTR:
- /* Setattr on inode */
- nblocks += 1;
- break;
- default: CERROR("unknown transaction start op %d\n", op);
- LBUG();
- }
-
- lock_kernel();
- handle = journal_start(EXTN_JOURNAL(inode), nblocks);
- unlock_kernel();
-
- return handle;
-}
-
-static int mds_extN_commit(struct inode *inode, void *handle)
-{
- int rc;
-
- lock_kernel();
- rc = journal_stop((handle_t *)handle);
- unlock_kernel();
-
- return rc;
-}
-
-static int mds_extN_setattr(struct dentry *dentry, void *handle,
- struct iattr *iattr)
-{
- struct inode *inode = dentry->d_inode;
- int rc;
-
- lock_kernel();
- if (inode->i_op->setattr)
- rc = inode->i_op->setattr(dentry, iattr);
- else
- rc = inode_setattr(inode, iattr);
-
- unlock_kernel();
-
- return rc;
-}
-
-static int mds_extN_set_md(struct inode *inode, void *handle,
- struct lov_mds_md *lmm, int lmm_size)
-{
- int rc;
-
- down(&inode->i_sem);
- lock_kernel();
- rc = extN_xattr_set(handle, inode, EXTN_XATTR_INDEX_LUSTRE,
- XATTR_LUSTRE_MDS_OBJID, lmm, lmm_size, 0);
- unlock_kernel();
- up(&inode->i_sem);
-
- if (rc) {
- CERROR("error adding objectid "LPX64" to inode %ld: %d\n",
- lmm->lmm_object_id, inode->i_ino, rc);
- if (rc != -ENOSPC) LBUG();
- }
- return rc;
-}
-
-static int mds_extN_get_md(struct inode *inode, struct lov_mds_md *lmm,int size)
-{
- int rc;
-
- down(&inode->i_sem);
- lock_kernel();
- rc = extN_xattr_get(inode, EXTN_XATTR_INDEX_LUSTRE,
- XATTR_LUSTRE_MDS_OBJID, lmm, size);
- unlock_kernel();
- up(&inode->i_sem);
-
- /* This gives us the MD size */
- if (lmm == NULL)
- return (rc == -ENODATA) ? 0 : rc;
-
- if (rc < 0) {
- CDEBUG(D_INFO, "error getting EA %s from MDS inode %ld: "
- "rc = %d\n", XATTR_LUSTRE_MDS_OBJID, inode->i_ino, rc);
- memset(lmm, 0, size);
- return (rc == -ENODATA) ? 0 : rc;
- }
-
- /* This field is byteswapped because it appears in the
- * catalogue. All others are opaque to the MDS */
- lmm->lmm_object_id = le64_to_cpu(lmm->lmm_object_id);
-
- return rc;
-}
-
-static ssize_t mds_extN_readpage(struct file *file, char *buf, size_t count,
- loff_t *offset)
-{
- struct inode *inode = file->f_dentry->d_inode;
- int rc = 0;
-
- if (S_ISREG(inode->i_mode))
- rc = file->f_op->read(file, buf, count, offset);
- else {
- struct buffer_head *bh;
-
- /* FIXME: this assumes the blocksize == count, but the calling
- * function will detect this as an error for now */
- bh = extN_bread(NULL, inode,
- *offset >> inode->i_sb->s_blocksize_bits,
- 0, &rc);
-
- if (bh) {
- memcpy(buf, bh->b_data, inode->i_blksize);
- brelse(bh);
- rc = inode->i_blksize;
- }
- }
-
- return rc;
-}
-
-static void mds_extN_delete_inode(struct inode *inode)
-{
- if (S_ISREG(inode->i_mode)) {
- void *handle = mds_extN_start(inode, MDS_FSOP_UNLINK);
-
- if (IS_ERR(handle)) {
- CERROR("unable to start transaction");
- EXIT;
- return;
- }
- if (mds_extN_set_md(inode, handle, NULL, 0))
- CERROR("error clearing objid on %ld\n", inode->i_ino);
-
- if (mds_extN_fs_ops.cl_delete_inode)
- mds_extN_fs_ops.cl_delete_inode(inode);
-
- if (mds_extN_commit(inode, handle))
- CERROR("error closing handle on %ld\n", inode->i_ino);
- } else
- mds_extN_fs_ops.cl_delete_inode(inode);
-}
-
-static void mds_extN_callback_status(struct journal_callback *jcb, int error)
-{
- struct mds_cb_data *mcb = (struct mds_cb_data *)jcb;
-
- CDEBUG(D_EXT2, "got callback for last_rcvd "LPD64": rc = %d\n",
- mcb->cb_last_rcvd, error);
- if (!error && mcb->cb_last_rcvd > mcb->cb_mds->mds_last_committed)
- mcb->cb_mds->mds_last_committed = mcb->cb_last_rcvd;
-
- kmem_cache_free(mcb_cache, mcb);
- --mcb_cache_count;
-}
-
-static int mds_extN_set_last_rcvd(struct mds_obd *mds, void *handle)
-{
- struct mds_cb_data *mcb;
-
- mcb = kmem_cache_alloc(mcb_cache, GFP_NOFS);
- if (!mcb)
- RETURN(-ENOMEM);
-
- ++mcb_cache_count;
- mcb->cb_mds = mds;
- mcb->cb_last_rcvd = mds->mds_last_rcvd;
-
-#ifdef HAVE_JOURNAL_CALLBACK_STATUS
- CDEBUG(D_EXT2, "set callback for last_rcvd: "LPD64"\n",
- mcb->cb_last_rcvd);
- lock_kernel();
- /* Note that an "incompatible pointer" warning here is OK for now */
- journal_callback_set(handle, mds_extN_callback_status,
- (struct journal_callback *)mcb);
- unlock_kernel();
-#else
-#warning "no journal callback kernel patch, faking it..."
- {
- static long next = 0;
-
- if (time_after(jiffies, next)) {
- CERROR("no journal callback kernel patch, faking it...\n");
- next = jiffies + 300 * HZ;
- }
-
- mds_extN_callback_status((struct journal_callback *)mcb, 0);
-#endif
-
- return 0;
-}
-
-static int mds_extN_journal_data(struct file *filp)
-{
- struct inode *inode = filp->f_dentry->d_inode;
-
- EXTN_I(inode)->i_flags |= EXTN_JOURNAL_DATA_FL;
-
- return 0;
-}
-
-/*
- * We need to hack the return value for the free inode counts because
- * the current EA code requires one filesystem block per inode with EAs,
- * so it is possible to run out of blocks before we run out of inodes.
- *
- * This can be removed when the extN EA code is fixed.
- */
-static int mds_extN_statfs(struct super_block *sb, struct statfs *sfs)
-{
- int rc = vfs_statfs(sb, sfs);
-
- if (!rc && sfs->f_bfree < sfs->f_ffree)
- sfs->f_ffree = sfs->f_bfree;
-
- return rc;
-}
-
-static struct mds_fs_operations mds_extN_fs_ops = {
- fs_owner: THIS_MODULE,
- fs_start: mds_extN_start,
- fs_commit: mds_extN_commit,
- fs_setattr: mds_extN_setattr,
- fs_set_md: mds_extN_set_md,
- fs_get_md: mds_extN_get_md,
- fs_readpage: mds_extN_readpage,
- fs_delete_inode: mds_extN_delete_inode,
- cl_delete_inode: clear_inode,
- fs_journal_data: mds_extN_journal_data,
- fs_set_last_rcvd: mds_extN_set_last_rcvd,
- fs_statfs: mds_extN_statfs,
-};
-
-static int __init mds_extN_init(void)
-{
- int rc;
-
- //rc = extN_xattr_register();
- mcb_cache = kmem_cache_create("mds_extN_mcb",
- sizeof(struct mds_cb_data), 0,
- 0, NULL, NULL);
- if (!mcb_cache) {
- CERROR("error allocating MDS journal callback cache\n");
- GOTO(out, rc = -ENOMEM);
- }
-
- rc = mds_register_fs_type(&mds_extN_fs_ops, "extN");
-
- if (rc)
- kmem_cache_destroy(mcb_cache);
-out:
- return rc;
-}
-
-static void __exit mds_extN_exit(void)
-{
- int rc;
-
- mds_unregister_fs_type("extN");
- rc = kmem_cache_destroy(mcb_cache);
-
- if (rc || mcb_cache_count) {
- CERROR("can't free MDS callback cache: count %d, rc = %d\n",
- mcb_cache_count, rc);
- }
-
- //rc = extN_xattr_unregister();
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre MDS extN Filesystem Helper v0.1");
-MODULE_LICENSE("GPL");
-
-module_init(mds_extN_init);
-module_exit(mds_extN_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * linux/mds/mds_fs.c
- *
- * Lustre Metadata Server (MDS) filesystem interface code
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * by Andreas Dilger <adilger@clusterfs.com>
- *
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_MDS
-
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/lustre_mds.h>
-#include <linux/obd_class.h>
-#include <linux/obd_support.h>
-#include <linux/lustre_lib.h>
-
-LIST_HEAD(mds_fs_types);
-
-struct mds_fs_type {
- struct list_head mft_list;
- struct mds_fs_operations *mft_ops;
- char *mft_name;
-};
-
-/* This limit is arbitrary, but for now we fit it in 1 page (32k clients) */
-#define MDS_MAX_CLIENTS (PAGE_SIZE * 8)
-#define MDS_MAX_CLIENT_WORDS (MDS_MAX_CLIENTS / sizeof(unsigned long))
-
-static unsigned long last_rcvd_slots[MDS_MAX_CLIENT_WORDS];
-
-#define LAST_RCVD "last_rcvd"
-
-/* Add client data to the MDS. We use a bitmap to locate a free space
- * in the last_rcvd file if cl_off is -1 (i.e. a new client).
- * Otherwise, we have just read the data from the last_rcvd file and
- * we know its offset.
- */
-int mds_client_add(struct mds_obd *mds, struct mds_export_data *med, int cl_off)
-{
- int new_client = (cl_off == -1);
-
- /* the bitmap operations can handle cl_off > sizeof(long) * 8, so
- * there's no need for extra complication here
- */
- if (new_client) {
- cl_off = find_first_zero_bit(last_rcvd_slots, MDS_MAX_CLIENTS);
- repeat:
- if (cl_off >= MDS_MAX_CLIENTS) {
- CERROR("no room for clients - fix MDS_MAX_CLIENTS\n");
- return -ENOMEM;
- }
- if (test_and_set_bit(cl_off, last_rcvd_slots)) {
- CERROR("MDS client %d: found bit is set in bitmap\n",
- cl_off);
- cl_off = find_next_zero_bit(last_rcvd_slots,
- MDS_MAX_CLIENTS, cl_off);
- goto repeat;
- }
- } else {
- if (test_and_set_bit(cl_off, last_rcvd_slots)) {
- CERROR("MDS client %d: bit already set in bitmap!!\n",
- cl_off);
- LBUG();
- }
- }
-
- CDEBUG(D_INFO, "client at offset %d with UUID '%s' added\n",
- cl_off, med->med_mcd->mcd_uuid);
-
- med->med_off = cl_off;
-
- if (new_client) {
- struct obd_run_ctxt saved;
- loff_t off = MDS_LR_CLIENT + (cl_off * MDS_LR_SIZE);
- ssize_t written;
-
- push_ctxt(&saved, &mds->mds_ctxt, NULL);
- written = lustre_fwrite(mds->mds_rcvd_filp,
- (char *)med->med_mcd,
- sizeof(*med->med_mcd), &off);
- pop_ctxt(&saved, &mds->mds_ctxt, NULL);
-
- if (written != sizeof(*med->med_mcd)) {
- if (written < 0)
- RETURN(written);
- RETURN(-EIO);
- }
- }
- return 0;
-}
-
-int mds_client_free(struct obd_export *exp)
-{
- struct mds_export_data *med = &exp->exp_mds_data;
- struct mds_obd *mds = &exp->exp_obd->u.mds;
- struct mds_client_data zero_mcd;
- struct obd_run_ctxt saved;
- int written;
- loff_t off;
-
- if (!med->med_mcd)
- RETURN(0);
-
- CDEBUG(D_INFO, "freeing client at offset %d with UUID '%s'\n",
- med->med_off, med->med_mcd->mcd_uuid);
-
- if (!test_and_clear_bit(med->med_off, last_rcvd_slots)) {
- CERROR("MDS client %d: bit already clear in bitmap!!\n",
- med->med_off);
- LBUG();
- }
-
- off = med->med_off;
-
- memset(&zero_mcd, 0, sizeof zero_mcd);
- push_ctxt(&saved, &mds->mds_ctxt, NULL);
- written = lustre_fwrite(mds->mds_rcvd_filp, (const char *)&zero_mcd,
- sizeof zero_mcd, &off);
- pop_ctxt(&saved, &mds->mds_ctxt, NULL);
-
- if (written != sizeof zero_mcd) {
- CERROR("error zeroing out client %s off %d in %s: %d\n",
- med->med_mcd->mcd_uuid, med->med_off, LAST_RCVD,
- written);
- LBUG();
- } else {
- CDEBUG(D_INFO, "zeroed out disconnecting client %s at off %d\n",
- med->med_mcd->mcd_uuid, med->med_off);
- }
-
- OBD_FREE(med->med_mcd, sizeof(*med->med_mcd));
-
- return 0;
-}
-
-static int mds_server_free_data(struct mds_obd *mds)
-{
- OBD_FREE(mds->mds_server_data, sizeof(*mds->mds_server_data));
- mds->mds_server_data = NULL;
-
- return 0;
-}
-
-static int mds_read_last_rcvd(struct obd_device *obddev, struct file *f)
-{
- struct mds_obd *mds = &obddev->u.mds;
- struct mds_server_data *msd;
- struct mds_client_data *mcd = NULL;
- loff_t off = 0;
- int cl_off;
- int max_off = f->f_dentry->d_inode->i_size / sizeof(*mcd);
- __u64 last_rcvd = 0;
- __u64 last_mount;
- int rc = 0;
-
- OBD_ALLOC(msd, sizeof(*msd));
- if (!msd)
- RETURN(-ENOMEM);
- rc = lustre_fread(f, (char *)msd, sizeof(*msd), &off);
-
- mds->mds_server_data = msd;
- if (rc == 0) {
- CERROR("empty MDS %s, new MDS?\n", LAST_RCVD);
- RETURN(0);
- }
-
- if (rc != sizeof(*msd)) {
- CERROR("error reading MDS %s: rc = %d\n", LAST_RCVD, rc);
- if (rc > 0) {
- rc = -EIO;
- }
- GOTO(err_msd, rc);
- }
-
- /*
- * When we do a clean MDS shutdown, we save the last_rcvd into
- * the header. If we find clients with higher last_rcvd values
- * then those clients may need recovery done.
- */
- last_rcvd = le64_to_cpu(msd->msd_last_rcvd);
- mds->mds_last_rcvd = last_rcvd;
- CDEBUG(D_INODE, "got %Lu for server last_rcvd value\n",
- (unsigned long long)last_rcvd);
-
- last_mount = le64_to_cpu(msd->msd_mount_count);
- mds->mds_mount_count = last_mount;
- CDEBUG(D_INODE, "got %Lu for server last_mount value\n",
- (unsigned long long)last_mount);
-
- for (off = MDS_LR_CLIENT, cl_off = 0;
- off < max_off;
- off += MDS_LR_SIZE, cl_off++) {
- int mount_age;
-
- if (!mcd) {
- OBD_ALLOC(mcd, sizeof(*mcd));
- if (!mcd)
- GOTO(err_msd, rc = -ENOMEM);
- }
-
- rc = lustre_fread(f, (char *)mcd, sizeof(*mcd), &off);
- if (rc != sizeof(*mcd)) {
- CERROR("error reading MDS %s offset %d: rc = %d\n",
- LAST_RCVD, cl_off, rc);
- if (rc > 0)
- rc = -EIO;
- break;
- }
-
- if (mcd->mcd_uuid[0] == '\0') {
- CDEBUG(D_INFO, "skipping zeroed client at offset %d\n",
- cl_off);
- continue;
- }
-
- last_rcvd = le64_to_cpu(mcd->mcd_last_rcvd);
-
- /* The exports are cleaned up by mds_disconnect, so they
- * need to be set up like real exports also.
- */
- mount_age = last_mount - le64_to_cpu(mcd->mcd_mount_count);
- if (last_rcvd && mount_age < MDS_MOUNT_RECOV) {
- struct obd_export *exp = class_new_export(obddev);
- struct mds_export_data *med;
-
- if (!exp) {
- rc = -ENOMEM;
- break;
- }
-
- med = &exp->exp_mds_data;
- med->med_mcd = mcd;
- mds_client_add(mds, med, cl_off);
- /* XXX put this in a helper if it gets more complex */
- INIT_LIST_HEAD(&med->med_open_head);
- spin_lock_init(&med->med_open_lock);
-
- mcd = NULL;
- mds->mds_recoverable_clients++;
- MOD_INC_USE_COUNT;
- } else {
- CDEBUG(D_INFO,
- "discarded client %d, UUID '%s', count %Ld\n",
- cl_off, mcd->mcd_uuid,
- (long long)le64_to_cpu(mcd->mcd_mount_count));
- }
-
- if (last_rcvd > mds->mds_last_rcvd) {
- CDEBUG(D_OTHER,
- "client at offset %d has last_rcvd = %Lu\n",
- cl_off, (unsigned long long)last_rcvd);
- mds->mds_last_rcvd = last_rcvd;
- }
- }
-
- mds->mds_last_committed = mds->mds_last_rcvd;
- if (mds->mds_recoverable_clients) {
- CERROR("need recovery: %d recoverable clients, last_rcvd %Lu\n",
- mds->mds_recoverable_clients, mds->mds_last_rcvd);
- }
-
- if (mcd)
- OBD_FREE(mcd, sizeof(*mcd));
-
- return 0;
-
-err_msd:
- mds_server_free_data(mds);
- return rc;
-}
-
-static int mds_fs_prep(struct obd_device *obddev)
-{
- struct mds_obd *mds = &obddev->u.mds;
- struct obd_run_ctxt saved;
- struct dentry *dentry;
- struct file *f;
- int rc;
-
- push_ctxt(&saved, &mds->mds_ctxt, NULL);
- dentry = simple_mkdir(current->fs->pwd, "ROOT", 0755);
- if (IS_ERR(dentry)) {
- rc = PTR_ERR(dentry);
- CERROR("cannot create ROOT directory: rc = %d\n", rc);
- GOTO(err_pop, rc);
- }
-
- mds->mds_rootfid.id = dentry->d_inode->i_ino;
- mds->mds_rootfid.generation = dentry->d_inode->i_generation;
- mds->mds_rootfid.f_type = S_IFDIR;
-
- dput(dentry);
-
- dentry = simple_mkdir(current->fs->pwd, "FH", 0700);
- if (IS_ERR(dentry)) {
- rc = PTR_ERR(dentry);
- CERROR("cannot create FH directory: rc = %d\n", rc);
- GOTO(err_pop, rc);
- }
- /* XXX probably want to hold on to this later... */
- dput(dentry);
-
- f = filp_open(LAST_RCVD, O_RDWR | O_CREAT, 0644);
- if (IS_ERR(f)) {
- rc = PTR_ERR(f);
- CERROR("cannot open/create %s file: rc = %d\n", LAST_RCVD, rc);
- GOTO(err_pop, rc = PTR_ERR(f));
- }
- if (!S_ISREG(f->f_dentry->d_inode->i_mode)) {
- CERROR("%s is not a regular file!: mode = %o\n", LAST_RCVD,
- f->f_dentry->d_inode->i_mode);
- GOTO(err_pop, rc = -ENOENT);
- }
-
- rc = mds_fs_journal_data(mds, f);
- if (rc) {
- CERROR("cannot journal data on %s: rc = %d\n", LAST_RCVD, rc);
- GOTO(err_filp, rc);
- }
-
- rc = mds_read_last_rcvd(obddev, f);
- if (rc) {
- CERROR("cannot read %s: rc = %d\n", LAST_RCVD, rc);
- GOTO(err_client, rc);
- }
- mds->mds_rcvd_filp = f;
-err_pop:
- pop_ctxt(&saved, &mds->mds_ctxt, NULL);
-
- return rc;
-
-err_client:
- class_disconnect_all(obddev);
-err_filp:
- if (filp_close(f, 0))
- CERROR("can't close %s after error\n", LAST_RCVD);
- goto err_pop;
-}
-
-static struct mds_fs_operations *mds_search_fs_type(const char *name)
-{
- struct list_head *p;
- struct mds_fs_type *type;
-
- /* lock mds_fs_types list */
- list_for_each(p, &mds_fs_types) {
- type = list_entry(p, struct mds_fs_type, mft_list);
- if (!strcmp(type->mft_name, name)) {
- /* unlock mds_fs_types list */
- return type->mft_ops;
- }
- }
- /* unlock mds_fs_types list */
- return NULL;
-}
-
-int mds_register_fs_type(struct mds_fs_operations *ops, const char *name)
-{
- struct mds_fs_operations *found;
- struct mds_fs_type *type;
-
- if ((found = mds_search_fs_type(name))) {
- if (found != ops) {
- CERROR("different operations for type %s\n", name);
- RETURN(-EEXIST);
- }
- return 0;
- }
- OBD_ALLOC(type, sizeof(*type));
- if (!type)
- RETURN(-ENOMEM);
-
- INIT_LIST_HEAD(&type->mft_list);
- type->mft_ops = ops;
- type->mft_name = strdup(name);
- if (!type->mft_name) {
- OBD_FREE(type, sizeof(*type));
- RETURN(-ENOMEM);
- }
- MOD_INC_USE_COUNT;
- list_add(&type->mft_list, &mds_fs_types);
-
- return 0;
-}
-
-void mds_unregister_fs_type(const char *name)
-{
- struct list_head *p;
-
- /* lock mds_fs_types list */
- list_for_each(p, &mds_fs_types) {
- struct mds_fs_type *type;
-
- type = list_entry(p, struct mds_fs_type, mft_list);
- if (!strcmp(type->mft_name, name)) {
- list_del(p);
- kfree(type->mft_name);
- OBD_FREE(type, sizeof(*type));
- MOD_DEC_USE_COUNT;
- break;
- }
- }
- /* unlock mds_fs_types list */
-}
-
-struct mds_fs_operations *mds_fs_get_ops(char *fstype)
-{
- struct mds_fs_operations *fs_ops;
-
- if (!(fs_ops = mds_search_fs_type(fstype))) {
- char name[32];
- int rc;
-
- snprintf(name, sizeof(name) - 1, "mds_%s", fstype);
- name[sizeof(name) - 1] = '\0';
-
- if ((rc = request_module(name))) {
- fs_ops = mds_search_fs_type(fstype);
- CDEBUG(D_INFO, "Loaded module '%s'\n", name);
- if (!fs_ops)
- rc = -ENOENT;
- }
-
- if (rc) {
- CERROR("Can't find MDS fs interface '%s'\n", name);
- RETURN(ERR_PTR(rc));
- }
- }
- __MOD_INC_USE_COUNT(fs_ops->fs_owner);
-
- return fs_ops;
-}
-
-void mds_fs_put_ops(struct mds_fs_operations *fs_ops)
-{
- __MOD_DEC_USE_COUNT(fs_ops->fs_owner);
-}
-
-int mds_fs_setup(struct obd_device *obddev, struct vfsmount *mnt)
-{
- struct mds_obd *mds = &obddev->u.mds;
- int rc;
-
- mds->mds_fsops = mds_fs_get_ops(mds->mds_fstype);
- if (IS_ERR(mds->mds_fsops))
- RETURN(PTR_ERR(mds->mds_fsops));
-
- mds->mds_vfsmnt = mnt;
-
- OBD_SET_CTXT_MAGIC(&mds->mds_ctxt);
- mds->mds_ctxt.pwdmnt = mnt;
- mds->mds_ctxt.pwd = mnt->mnt_root;
- mds->mds_ctxt.fs = get_ds();
-
- /*
- * Replace the client filesystem delete_inode method with our own,
- * so that we can clear the object ID before the inode is deleted.
- * The fs_delete_inode method will call cl_delete_inode for us.
- * We need to do this for the MDS superblock only, hence we install
- * a modified copy of the original superblock method table.
- *
- * We still assume that there is only a single MDS client filesystem
- * type, as we don't have access to the mds struct in delete_inode
- * and store the client delete_inode method in a global table. This
- * will only become a problem if/when multiple MDSs are running on a
- * single host with different underlying filesystems.
- */
- OBD_ALLOC(mds->mds_sop, sizeof(*mds->mds_sop));
- if (!mds->mds_sop)
- GOTO(out_dec, rc = -ENOMEM);
-
- memcpy(mds->mds_sop, mds->mds_sb->s_op, sizeof(*mds->mds_sop));
- mds->mds_fsops->cl_delete_inode = mds->mds_sop->delete_inode;
- mds->mds_sop->delete_inode = mds->mds_fsops->fs_delete_inode;
- mds->mds_sb->s_op = mds->mds_sop;
-
- rc = mds_fs_prep(obddev);
-
- if (rc)
- GOTO(out_free, rc);
-
- return 0;
-
-out_free:
- OBD_FREE(mds->mds_sop, sizeof(*mds->mds_sop));
-out_dec:
- mds_fs_put_ops(mds->mds_fsops);
- return rc;
-}
-
-void mds_fs_cleanup(struct obd_device *obddev)
-{
- struct mds_obd *mds = &obddev->u.mds;
-
- class_disconnect_all(obddev); /* this cleans up client info too */
- mds_server_free_data(mds);
-
- OBD_FREE(mds->mds_sop, sizeof(*mds->mds_sop));
- mds_fs_put_ops(mds->mds_fsops);
-}
-
-EXPORT_SYMBOL(mds_register_fs_type);
-EXPORT_SYMBOL(mds_unregister_fs_type);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * linux/mds/mds_lov.c
- *
- * Lustre Metadata Server (mds) handling of striped file data
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * by Peter Braam <braam@clusterfs.com> &
- *
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_MDS
-
-#include <linux/module.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_idl.h>
-#include <linux/obd_class.h>
-#include <linux/obd_lov.h>
-#include <linux/lustre_lib.h>
-
-/* lov_unpackdesc() is in lov/lov_pack.c */
-
-void lov_packdesc(struct lov_desc *ld)
-{
- ld->ld_tgt_count = HTON__u32(ld->ld_tgt_count);
- ld->ld_default_stripe_count = HTON__u32(ld->ld_default_stripe_count);
- ld->ld_default_stripe_size = HTON__u32(ld->ld_default_stripe_size);
- ld->ld_pattern = HTON__u32(ld->ld_pattern);
-}
-
-int mds_set_lovdesc(struct obd_device *obd, struct lov_desc *desc,
- obd_uuid_t *uuidarray)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct obd_run_ctxt saved;
- struct file *f;
- int tgt_count;
- int rc;
- int i;
- ENTRY;
-
- tgt_count = desc->ld_tgt_count;
- lov_packdesc(desc);
-
- push_ctxt(&saved, &mds->mds_ctxt, NULL);
- f = filp_open("LOVDESC", O_CREAT|O_RDWR, 0644);
- if (IS_ERR(f)) {
- CERROR("Cannot open/create LOVDESC file\n");
- GOTO(out, rc = PTR_ERR(f));
- }
-
- rc = lustre_fwrite(f, (char *)desc, sizeof(*desc), &f->f_pos);
- if (filp_close(f, 0))
- CERROR("Error closing LOVDESC file\n");
- if (rc != sizeof(*desc)) {
- CERROR("Cannot open/create LOVDESC file\n");
- GOTO(out, rc = PTR_ERR(f));
- }
-
- f = filp_open("LOVTGTS", O_CREAT|O_RDWR, 0644);
- if (IS_ERR(f)) {
- CERROR("Cannot open/create LOVTGTS file\n");
- GOTO(out, rc = PTR_ERR(f));
- }
-
- rc = 0;
- for (i = 0; i < tgt_count ; i++) {
- rc = lustre_fwrite(f, uuidarray[i],
- sizeof(uuidarray[i]), &f->f_pos);
- if (rc != sizeof(uuidarray[i])) {
- CERROR("cannot write LOV UUID %s (%d)\n",
- uuidarray[i], i);
- if (rc >= 0)
- rc = -EIO;
- break;
- } else
- rc = 0;
- }
- if (filp_close(f, 0))
- CERROR("Error closing LOVTGTS file\n");
-
-out:
- pop_ctxt(&saved, &mds->mds_ctxt, NULL);
- RETURN(rc);
-}
-
-int mds_get_lovdesc(struct mds_obd *mds, struct lov_desc *desc)
-{
- struct obd_run_ctxt saved;
- struct file *f;
- int rc;
- ENTRY;
-
- push_ctxt(&saved, &mds->mds_ctxt, NULL);
- f = filp_open("LOVDESC", O_RDONLY, 0644);
- if (IS_ERR(f)) {
- CERROR("Cannot open LOVDESC file\n");
- GOTO(out, rc = PTR_ERR(f));
- }
-
- rc = lustre_fread(f, (char *)desc, sizeof(*desc), &f->f_pos);
- if (filp_close(f, 0))
- CERROR("Error closing LOVDESC file\n");
-
- if (rc != sizeof(*desc)) {
- CERROR("Cannot read LOVDESC file: rc = %d\n", rc);
- GOTO(out, rc = -EIO);
- } else
- rc = 0;
- EXIT;
-out:
- pop_ctxt(&saved, &mds->mds_ctxt, NULL);
-
- return rc;
-}
-
-int mds_get_lovtgts(struct mds_obd *mds, int tgt_count,obd_uuid_t *uuidarray)
-{
- struct obd_run_ctxt saved;
- struct file *f;
- int rc;
- int rc2;
-
- push_ctxt(&saved, &mds->mds_ctxt, NULL);
- f = filp_open("LOVTGTS", O_RDONLY, 0644);
- if (IS_ERR(f)) {
- CERROR("Cannot open LOVTGTS file\n");
- GOTO(out, rc = PTR_ERR(f));
- }
-
- rc = lustre_fread(f, (char *)uuidarray, tgt_count * sizeof(*uuidarray),
- &f->f_pos);
- rc2 = filp_close(f, 0);
- if (rc2)
- CERROR("Error closing LOVTGTS file: rc = %d\n", rc2);
-
- if (rc != tgt_count * sizeof(*uuidarray)) {
- CERROR("Error reading LOVTGTS file: rc = %d\n", rc);
- if (rc >= 0)
- rc = -EIO;
- GOTO(out, rc);
- } else
- rc = 0;
- EXIT;
-out:
- pop_ctxt(&saved, &mds->mds_ctxt, NULL);
-
- RETURN(rc);
-}
-
-int mds_iocontrol(unsigned int cmd, struct lustre_handle *conn,
- int len, void *karg, void *uarg)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct obd_ioctl_data *data = karg;
- struct lov_desc *desc;
- obd_uuid_t *uuidarray;
- int count;
- int rc;
-
-
- switch (cmd) {
- case OBD_IOC_LOV_SET_CONFIG:
- desc = (struct lov_desc *)data->ioc_inlbuf1;
- if (sizeof(*desc) > data->ioc_inllen1) {
- CERROR("descriptor size wrong\n");
- RETURN(-EINVAL);
- }
-
- count = desc->ld_tgt_count;
- uuidarray = (obd_uuid_t *)data->ioc_inlbuf2;
- if (sizeof(*uuidarray) * count != data->ioc_inllen2) {
- CERROR("UUID array size wrong\n");
- RETURN(-EINVAL);
- }
- rc = mds_set_lovdesc(obd, desc, uuidarray);
-
- RETURN(rc);
- case OBD_IOC_LOV_GET_CONFIG:
- desc = (struct lov_desc *)data->ioc_inlbuf1;
- if (sizeof(*desc) > data->ioc_inllen1) {
- CERROR("descriptor size wrong\n");
- RETURN(-EINVAL);
- }
-
- count = desc->ld_tgt_count;
- uuidarray = (obd_uuid_t *)data->ioc_inlbuf2;
- if (sizeof(*uuidarray) * count != data->ioc_inllen2) {
- CERROR("UUID array size wrong\n");
- RETURN(-EINVAL);
- }
- rc = mds_get_lovdesc(&obd->u.mds, desc);
- if (desc->ld_tgt_count > count) {
- CERROR("UUID array size too small\n");
- RETURN(-ENOSPC);
- }
- rc = mds_get_lovtgts(&obd->u.mds, desc->ld_tgt_count, uuidarray);
-
- RETURN(rc);
- default:
- RETURN(-EINVAL);
- }
-
- RETURN(0);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * linux/mds/mds_reint.c
- * Lustre Metadata Server (mds) reintegration routines
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Peter Braam <braam@clusterfs.com>
- * Author: Andreas Dilger <adilger@clusterfs.com>
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_MDS
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/obd.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_idl.h>
-#include <linux/lustre_mds.h>
-#include <linux/lustre_dlm.h>
-#include <linux/obd_class.h>
-
-extern inline struct mds_obd *mds_req2mds(struct ptlrpc_request *req);
-
-void mds_start_transno(struct mds_obd *mds)
-{
- ENTRY;
- down(&mds->mds_transno_sem);
-}
-
-/* Assumes caller has already pushed us into the kernel context. */
-int mds_finish_transno(struct mds_obd *mds, void *handle,
- struct ptlrpc_request *req, int rc)
-{
- struct mds_export_data *med = &req->rq_export->exp_mds_data;
- struct mds_client_data *mcd = med->med_mcd;
- __u64 last_rcvd;
- loff_t off;
- ssize_t written;
-
- /* Propagate error code. */
- if (rc)
- goto out;
-
- /* we don't allocate new transnos for replayed requests */
- if (req->rq_level == LUSTRE_CONN_RECOVD) {
- rc = 0;
- goto out;
- }
-
- off = MDS_LR_CLIENT + med->med_off * MDS_LR_SIZE;
-
- last_rcvd = ++mds->mds_last_rcvd;
- req->rq_repmsg->transno = HTON__u64(last_rcvd);
- mcd->mcd_last_rcvd = cpu_to_le64(last_rcvd);
- mcd->mcd_mount_count = cpu_to_le64(mds->mds_mount_count);
- mcd->mcd_last_xid = cpu_to_le64(req->rq_xid);
-
- mds_fs_set_last_rcvd(mds, handle);
- written = lustre_fwrite(mds->mds_rcvd_filp, (char *)mcd, sizeof(*mcd),
- &off);
- CDEBUG(D_INODE, "wrote trans #"LPD64" for client %s at #%d: written = "
- "%d\n", last_rcvd, mcd->mcd_uuid, med->med_off, written);
-
- if (written == sizeof(*mcd))
- GOTO(out, rc = 0);
- CERROR("error writing to last_rcvd file: rc = %d\n", rc);
- if (written >= 0)
- GOTO(out, rc = -EIO);
-
- rc = 0;
-
- out:
- EXIT;
- up(&mds->mds_transno_sem);
- return rc;
-}
-
-/* In the write-back case, the client holds a lock on a subtree.
- * In the intent case, the client holds a lock on the child inode.
- * In the pathname case, the client (may) hold a lock on the child inode. */
-static int mds_reint_setattr(struct mds_update_record *rec, int offset,
- struct ptlrpc_request *req)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct obd_device *obd = req->rq_export->exp_obd;
- struct mds_body *body;
- struct dentry *de;
- struct inode *inode;
- void *handle;
- struct lustre_handle child_lockh;
- int rc = 0, err;
-
- if (req->rq_reqmsg->bufcount > offset + 1) {
- struct dentry *dir;
- struct lustre_handle dir_lockh;
- char *name;
- int namelen;
-
- /* a name was supplied by the client; fid1 is the directory */
- dir = mds_fid2locked_dentry(obd, rec->ur_fid1, NULL, LCK_PR,
- &dir_lockh);
- if (IS_ERR(dir)) {
- LBUG();
- GOTO(out_setattr, rc = PTR_ERR(dir));
- }
-
- name = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- namelen = req->rq_reqmsg->buflens[offset + 1] - 1;
- de = mds_name2locked_dentry(obd, dir, NULL, name, namelen,
- 0, &child_lockh, LCK_PR);
- l_dput(dir);
- if (IS_ERR(de)) {
- LBUG();
- GOTO(out_setattr_de, rc = PTR_ERR(de));
- }
- } else {
- de = mds_fid2dentry(mds, rec->ur_fid1, NULL);
- if (!de || IS_ERR(de)) {
- GOTO(out_setattr_de, rc = PTR_ERR(de));
- }
- }
- inode = de->d_inode;
- CDEBUG(D_INODE, "ino %ld\n", inode->i_ino);
-
- OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_SETATTR_WRITE,
- to_kdev_t(inode->i_sb->s_dev));
-
- mds_start_transno(mds);
- handle = mds_fs_start(mds, inode, MDS_FSOP_SETATTR);
- if (IS_ERR(handle)) {
- rc = PTR_ERR(handle);
- (void)mds_finish_transno(mds, handle, req, rc);
- GOTO(out_setattr_de, rc);
- }
-
- rc = mds_fs_setattr(mds, de, handle, &rec->ur_iattr);
-
- if (offset) {
- body = lustre_msg_buf(req->rq_repmsg, 1);
- mds_pack_inode2fid(&body->fid1, inode);
- mds_pack_inode2body(body, inode);
- }
-
- rc = mds_finish_transno(mds, handle, req, rc);
-
- err = mds_fs_commit(mds, de->d_inode, handle);
- if (err) {
- CERROR("error on commit: err = %d\n", err);
- if (!rc)
- rc = err;
- }
-
- EXIT;
-out_setattr_de:
- l_dput(de);
-out_setattr:
- req->rq_status = rc;
- return 0;
-}
-
-static int mds_reint_create(struct mds_update_record *rec, int offset,
- struct ptlrpc_request *req)
-{
- struct dentry *de = NULL;
- struct mds_obd *mds = mds_req2mds(req);
- struct obd_device *obd = req->rq_export->exp_obd;
- struct dentry *dchild = NULL;
- struct inode *dir;
- void *handle;
- struct lustre_handle lockh;
- int rc = 0, err, lock_mode, type = rec->ur_mode & S_IFMT;
- ENTRY;
-
- /* requests were at offset 2, replies go back at 1 */
- if (offset)
- offset = 1;
-
- LASSERT(!strcmp(req->rq_export->exp_obd->obd_type->typ_name, "mds"));
-
- lock_mode = (req->rq_reqmsg->opc == MDS_REINT) ? LCK_CW : LCK_PW;
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_REINT_CREATE))
- GOTO(out_create, rc = -ESTALE);
-
- de = mds_fid2locked_dentry(obd, rec->ur_fid1, NULL, lock_mode, &lockh);
- if (IS_ERR(de)) {
- rc = PTR_ERR(de);
- CERROR("parent lookup error %d\n", rc);
- LBUG();
- GOTO(out_create, rc);
- }
- dir = de->d_inode;
- CDEBUG(D_INODE, "parent ino %ld name %s mode %o\n",
- dir->i_ino, rec->ur_name, rec->ur_mode);
-
- ldlm_lock_dump((void *)(unsigned long)lockh.addr);
-
- down(&dir->i_sem);
- dchild = lookup_one_len(rec->ur_name, de, rec->ur_namelen - 1);
- if (IS_ERR(dchild)) {
- CERROR("child lookup error %ld\n", PTR_ERR(dchild));
- LBUG();
- GOTO(out_create_de, rc = -ESTALE);
- }
-
- if (dchild->d_inode) {
- struct mds_body *body;
- struct inode *inode = dchild->d_inode;
-
- CDEBUG(D_INODE, "child exists (dir %ld, name %s, ino %ld)\n",
- dir->i_ino, rec->ur_name, dchild->d_inode->i_ino);
-
- /* XXX check that mode is correct? */
-
- body = lustre_msg_buf(req->rq_repmsg, offset);
- mds_pack_inode2fid(&body->fid1, inode);
- mds_pack_inode2body(body, inode);
- if (S_ISREG(inode->i_mode))
- mds_pack_md(mds, req, offset + 1, body, inode);
-
- /* This isn't an error for RECREATE. */
- if (rec->ur_opcode & REINT_REPLAYING) {
- CDEBUG(D_INODE, "EEXIST suppressed for REPLAYING\n");
- rc = 0;
- } else {
- rc = -EEXIST;
- }
- GOTO(out_create_dchild, rc);
- }
-
- OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_CREATE_WRITE,
- to_kdev_t(dir->i_sb->s_dev));
-
- if (dir->i_mode & S_ISGID) {
- rec->ur_gid = dir->i_gid;
- if (S_ISDIR(rec->ur_mode))
- rec->ur_mode |= S_ISGID;
- }
-
- /* From here on, we must exit via a path that calls mds_finish_transno,
- * so that we release the mds_transno_sem (and, in the case of success,
- * update the transno correctly). out_create_commit and
- * out_transno_dchild are good candidates.
- */
- mds_start_transno(mds);
-
- switch (type) {
- case S_IFREG:{
- handle = mds_fs_start(mds, dir, MDS_FSOP_CREATE);
- if (IS_ERR(handle))
- GOTO(out_transno_dchild, rc = PTR_ERR(handle));
- rc = vfs_create(dir, dchild, rec->ur_mode);
- EXIT;
- break;
- }
- case S_IFDIR:{
- handle = mds_fs_start(mds, dir, MDS_FSOP_MKDIR);
- if (IS_ERR(handle))
- GOTO(out_transno_dchild, rc = PTR_ERR(handle));
- rc = vfs_mkdir(dir, dchild, rec->ur_mode);
- EXIT;
- break;
- }
- case S_IFLNK:{
- handle = mds_fs_start(mds, dir, MDS_FSOP_SYMLINK);
- if (IS_ERR(handle))
- GOTO(out_transno_dchild, rc = PTR_ERR(handle));
- rc = vfs_symlink(dir, dchild, rec->ur_name);
- EXIT;
- break;
- }
- case S_IFCHR:
- case S_IFBLK:
- case S_IFIFO:
- case S_IFSOCK:{
- int rdev = rec->ur_rdev;
- handle = mds_fs_start(mds, dir, MDS_FSOP_MKNOD);
- if (IS_ERR(handle))
- GOTO(out_transno_dchild, rc = PTR_ERR(handle));
- rc = vfs_mknod(dir, dchild, rec->ur_mode, rdev);
- EXIT;
- break;
- }
- default:
- CERROR("bad file type %o creating %s\n", type, rec->ur_name);
- handle = NULL; /* quell uninitialized warning */
- GOTO(out_transno_dchild, rc = -EINVAL);
- }
-
- if (rc) {
- CDEBUG(D_INODE, "error during create: %d\n", rc);
- GOTO(out_create_commit, rc);
- } else {
- struct iattr iattr;
- struct inode *inode = dchild->d_inode;
- struct mds_body *body;
-
- iattr.ia_atime = rec->ur_time;
- iattr.ia_ctime = rec->ur_time;
- iattr.ia_mtime = rec->ur_time;
- iattr.ia_uid = rec->ur_uid;
- iattr.ia_gid = rec->ur_gid;
- iattr.ia_valid = ATTR_UID | ATTR_GID | ATTR_ATIME |
- ATTR_MTIME | ATTR_CTIME;
-
- if (rec->ur_fid2->id) {
- LASSERT(rec->ur_opcode & REINT_REPLAYING);
- inode->i_generation = rec->ur_fid2->generation;
- /* Dirtied and committed by the upcoming setattr. */
- CDEBUG(D_INODE, "recreated ino %ld with gen %ld\n",
- inode->i_ino, inode->i_generation);
- } else {
- CDEBUG(D_INODE, "created ino %ld\n", inode->i_ino);
- }
-
- rc = mds_fs_setattr(mds, dchild, handle, &iattr);
- if (rc) {
- CERROR("error on setattr: rc = %d\n", rc);
- /* XXX should we abort here in case of error? */
- }
-
- body = lustre_msg_buf(req->rq_repmsg, offset);
- mds_pack_inode2fid(&body->fid1, inode);
- mds_pack_inode2body(body, inode);
- }
- EXIT;
-out_create_commit:
- if (rc) {
- rc = mds_finish_transno(mds, handle, req, rc);
- } else {
- rc = mds_finish_transno(mds, handle, req, rc);
- if (rc)
- GOTO(out_create_unlink, rc);
- }
- err = mds_fs_commit(mds, dir, handle);
- if (err) {
- CERROR("error on commit: err = %d\n", err);
- if (!rc)
- rc = err;
- }
-out_create_dchild:
- l_dput(dchild);
- ldlm_lock_decref(&lockh, lock_mode);
-out_create_de:
- up(&dir->i_sem);
- l_dput(de);
-out_create:
- req->rq_status = rc;
- return 0;
-
-out_transno_dchild:
- /* Need to release the transno lock, and then put the dchild. */
- LASSERT(rc);
- mds_finish_transno(mds, handle, req, rc);
- goto out_create_dchild;
-
-out_create_unlink:
- /* Destroy the file we just created. This should not need extra
- * journal credits, as we have already modified all of the blocks
- * needed in order to create the file in the first place.
- */
- switch (type) {
- case S_IFDIR:
- err = vfs_rmdir(dir, dchild);
- if (err)
- CERROR("failed rmdir in error path: rc = %d\n", err);
- break;
- default:
- err = vfs_unlink(dir, dchild);
- if (err)
- CERROR("failed unlink in error path: rc = %d\n", err);
- break;
- }
-
- goto out_create_commit;
-}
-
-static int mds_reint_unlink(struct mds_update_record *rec, int offset,
- struct ptlrpc_request *req)
-{
- struct dentry *de = NULL;
- struct dentry *dchild = NULL;
- struct mds_obd *mds = mds_req2mds(req);
- struct obd_device *obd = req->rq_export->exp_obd;
- struct mds_body *body = NULL;
- char *name;
- struct inode *dir, *inode;
- struct lustre_handle lockh, child_lockh;
- void *handle;
- int namelen, lock_mode, err, rc = 0;
- ENTRY;
-
- /* a name was supplied by the client; fid1 is the directory */
- lock_mode = (req->rq_reqmsg->opc == MDS_REINT) ? LCK_PW : LCK_PW;
- de = mds_fid2locked_dentry(obd, rec->ur_fid1, NULL, lock_mode, &lockh);
- if (IS_ERR(de)) {
- LBUG();
- RETURN(PTR_ERR(de));
- }
-
- if (OBD_FAIL_CHECK(OBD_FAIL_MDS_REINT_UNLINK))
- GOTO(out_unlink, rc = -ENOENT);
-
- name = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- namelen = req->rq_reqmsg->buflens[offset + 1] - 1;
-#warning "FIXME: if mds_name2locked_dentry decrefs this lock, we must not"
- memcpy(&child_lockh, &lockh, sizeof(child_lockh));
- dchild = mds_name2locked_dentry(obd, de, NULL, name, namelen,
- LCK_EX, &child_lockh, lock_mode);
-
- if (IS_ERR(dchild)) {
- LBUG();
- GOTO(out_unlink, rc = PTR_ERR(dchild));
- }
-
- dir = de->d_inode;
- inode = dchild->d_inode;
- CDEBUG(D_INODE, "parent ino %ld\n", dir->i_ino);
-
- if (!inode) {
- if (rec->ur_opcode & REINT_REPLAYING) {
- CDEBUG(D_INODE,
- "child missing (%ld/%s); OK for REPLAYING\n",
- dir->i_ino, rec->ur_name);
- rc = 0;
- } else {
- CDEBUG(D_INODE,
- "child doesn't exist (dir %ld, name %s)\n",
- dir->i_ino, rec->ur_name);
- rc = -ENOENT;
- }
- /* going to out_unlink_cancel causes an LBUG, don't know why */
- GOTO(out_unlink_dchild, rc);
- }
-
- if (offset) {
- /* XXX offset? */
- offset = 1;
-
- body = lustre_msg_buf(req->rq_repmsg, offset);
- mds_pack_inode2fid(&body->fid1, inode);
- mds_pack_inode2body(body, inode);
- }
-
- OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_UNLINK_WRITE,
- to_kdev_t(dir->i_sb->s_dev));
-
- mds_start_transno(mds);
- switch (rec->ur_mode /* & S_IFMT ? */) {
- case S_IFDIR:
- handle = mds_fs_start(mds, dir, MDS_FSOP_RMDIR);
- if (IS_ERR(handle))
- GOTO(out_unlink_cancel_transno, rc = PTR_ERR(handle));
- rc = vfs_rmdir(dir, dchild);
- break;
- case S_IFREG:
- /* get OBD EA data first so client can also destroy object */
- if ((inode->i_mode & S_IFMT) == S_IFREG && offset)
- mds_pack_md(mds, req, offset + 1, body, inode);
- /* no break */
- case S_IFLNK:
- case S_IFCHR:
- case S_IFBLK:
- case S_IFIFO:
- case S_IFSOCK:
- handle = mds_fs_start(mds, dir, MDS_FSOP_UNLINK);
- if (IS_ERR(handle))
- GOTO(out_unlink_cancel_transno, rc = PTR_ERR(handle));
- rc = vfs_unlink(dir, dchild);
- break;
- default:
- CERROR("bad file type %o unlinking %s\n", rec->ur_mode, name);
- handle = NULL;
- LBUG();
- GOTO(out_unlink_cancel_transno, rc = -EINVAL);
- }
-
- rc = mds_finish_transno(mds, handle, req, rc);
- err = mds_fs_commit(mds, dir, handle);
- if (err) {
- CERROR("error on commit: err = %d\n", err);
- if (!rc)
- rc = err;
- }
-
- EXIT;
-
-out_unlink_cancel:
- ldlm_lock_decref(&child_lockh, LCK_EX);
- err = ldlm_cli_cancel(&child_lockh);
- if (err < 0) {
- CERROR("failed to cancel child inode lock: err = %d\n", err);
- if (!rc)
- rc = -ENOLCK; /*XXX translate LDLM lock error */
- }
-out_unlink_dchild:
- l_dput(dchild);
- up(&dir->i_sem);
-out_unlink:
- ldlm_lock_decref(&lockh, lock_mode);
- l_dput(de);
- req->rq_status = rc;
- return 0;
-
-out_unlink_cancel_transno:
- rc = mds_finish_transno(mds, handle, req, rc);
- goto out_unlink_cancel;
-}
-
-static int mds_reint_link(struct mds_update_record *rec, int offset,
- struct ptlrpc_request *req)
-{
- struct obd_device *obd = req->rq_export->exp_obd;
- struct dentry *de_src = NULL;
- struct dentry *de_tgt_dir = NULL;
- struct dentry *dchild = NULL;
- struct mds_obd *mds = mds_req2mds(req);
- struct lustre_handle *handle, tgtlockh, srclockh;
- int lock_mode;
- __u64 res_id[3] = { 0 };
- int flags = 0;
- int rc = 0, err;
-
- ENTRY;
- de_src = mds_fid2dentry(mds, rec->ur_fid1, NULL);
- if (IS_ERR(de_src) || OBD_FAIL_CHECK(OBD_FAIL_MDS_REINT_LINK)) {
- GOTO(out_link, rc = -ESTALE);
- }
-
- /* plan to change the link count on this inode: write lock */
- lock_mode = (req->rq_reqmsg->opc == MDS_REINT) ? LCK_PW : LCK_PW;
- res_id[0] = de_src->d_inode->i_ino;
- res_id[1] = de_src->d_inode->i_generation;
-
- rc = ldlm_lock_match(obd->obd_namespace, res_id, LDLM_PLAIN,
- NULL, 0, lock_mode, &srclockh);
- if (rc == 0) {
- LDLM_DEBUG_NOLOCK("enqueue res "LPU64, res_id[0]);
- rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, NULL,
- res_id, LDLM_PLAIN, NULL, 0, lock_mode,
- &flags, ldlm_completion_ast,
- mds_blocking_ast, NULL, 0, &srclockh);
- if (rc != ELDLM_OK) {
- CERROR("lock enqueue: err: %d\n", rc);
- GOTO(out_link_src_put, rc = -EIO);
- }
- } else
- ldlm_lock_dump((void *)(unsigned long)srclockh.addr);
-
- de_tgt_dir = mds_fid2dentry(mds, rec->ur_fid2, NULL);
- if (IS_ERR(de_tgt_dir)) {
- GOTO(out_link_src, rc = -ESTALE);
- }
-
- lock_mode = (req->rq_reqmsg->opc == MDS_REINT) ? LCK_PW : LCK_PW;
- res_id[0] = de_tgt_dir->d_inode->i_ino;
- res_id[1] = de_tgt_dir->d_inode->i_generation;
-
- rc = ldlm_lock_match(obd->obd_namespace, res_id, LDLM_PLAIN,
- NULL, 0, lock_mode, &tgtlockh);
- if (rc == 0) {
- LDLM_DEBUG_NOLOCK("enqueue res "LPU64, res_id[0]);
- rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, NULL,
- res_id, LDLM_PLAIN, NULL, 0, lock_mode,
- &flags, ldlm_completion_ast,
- mds_blocking_ast, NULL, 0, &tgtlockh);
- if (rc != ELDLM_OK) {
- CERROR("lock enqueue: err: %d\n", rc);
- GOTO(out_link_tgt_dir_put, rc = -EIO);
- }
- } else
- ldlm_lock_dump((void *)(unsigned long)tgtlockh.addr);
-
- down(&de_tgt_dir->d_inode->i_sem);
- dchild = lookup_one_len(rec->ur_name, de_tgt_dir, rec->ur_namelen - 1);
- if (IS_ERR(dchild)) {
- CERROR("child lookup error %ld\n", PTR_ERR(dchild));
- GOTO(out_link_tgt_dir, rc = -ESTALE);
- }
-
- if (dchild->d_inode) {
- struct inode *inode = dchild->d_inode;
- /* in intent case ship back attributes to client */
- if (offset) {
- struct mds_body *body =
- lustre_msg_buf(req->rq_repmsg, 1);
-
- mds_pack_inode2fid(&body->fid1, inode);
- mds_pack_inode2body(body, inode);
- if (S_ISREG(inode->i_mode))
- mds_pack_md(mds, req, 2, body, inode);
- }
- if (rec->ur_opcode & REINT_REPLAYING) {
- /* XXX verify that the link is to the the right file? */
- rc = 0;
- CDEBUG(D_INODE,
- "child exists (dir %ld, name %s) (REPLAYING)\n",
- de_tgt_dir->d_inode->i_ino, rec->ur_name);
- } else {
- rc = -EEXIST;
- CERROR("child exists (dir %ld, name %s)\n",
- de_tgt_dir->d_inode->i_ino, rec->ur_name);
- }
- GOTO(out_link_dchild, rc);
- }
-
- OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_LINK_WRITE,
- to_kdev_t(de_src->d_inode->i_sb->s_dev));
-
- mds_start_transno(mds);
- handle = mds_fs_start(mds, de_tgt_dir->d_inode, MDS_FSOP_LINK);
- if (IS_ERR(handle)) {
- rc = PTR_ERR(handle);
- mds_finish_transno(mds, handle, req, rc);
- GOTO(out_link_dchild, rc);
- }
-
- rc = vfs_link(de_src, de_tgt_dir->d_inode, dchild);
- if (rc)
- CERROR("link error %d\n", rc);
- rc = mds_finish_transno(mds, handle, req, rc);
-
- err = mds_fs_commit(mds, de_tgt_dir->d_inode, handle);
- if (err) {
- CERROR("error on commit: err = %d\n", err);
- if (!rc)
- rc = err;
- }
- EXIT;
-
-out_link_dchild:
- l_dput(dchild);
-out_link_tgt_dir:
- ldlm_lock_decref(&tgtlockh, lock_mode);
-out_link_tgt_dir_put:
- up(&de_tgt_dir->d_inode->i_sem);
- l_dput(de_tgt_dir);
-out_link_src:
- ldlm_lock_decref(&srclockh, lock_mode);
-out_link_src_put:
- l_dput(de_src);
-out_link:
- req->rq_status = rc;
- return 0;
-}
-
-static int mds_reint_rename(struct mds_update_record *rec, int offset,
- struct ptlrpc_request *req)
-{
- struct obd_device *obd = req->rq_export->exp_obd;
- struct dentry *de_srcdir = NULL;
- struct dentry *de_tgtdir = NULL;
- struct dentry *de_old = NULL;
- struct dentry *de_new = NULL;
- struct mds_obd *mds = mds_req2mds(req);
- struct lustre_handle tgtlockh, srclockh, oldhandle;
- int flags = 0, lock_mode, rc = 0, err;
- void *handle;
- __u64 res_id[3] = { 0 };
- ENTRY;
-
- de_srcdir = mds_fid2dentry(mds, rec->ur_fid1, NULL);
- if (IS_ERR(de_srcdir))
- GOTO(out_rename, rc = -ESTALE);
-
- lock_mode = (req->rq_reqmsg->opc == MDS_REINT) ? LCK_PW : LCK_PW;
- res_id[0] = de_srcdir->d_inode->i_ino;
- res_id[1] = de_srcdir->d_inode->i_generation;
-
- rc = ldlm_lock_match(obd->obd_namespace, res_id, LDLM_PLAIN,
- NULL, 0, lock_mode, &srclockh);
- if (rc == 0) {
- LDLM_DEBUG_NOLOCK("enqueue res "LPU64, res_id[0]);
- rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, NULL,
- res_id, LDLM_PLAIN, NULL, 0, lock_mode,
- &flags, ldlm_completion_ast,
- mds_blocking_ast, NULL, 0, &srclockh);
- if (rc != ELDLM_OK) {
- CERROR("lock enqueue: err: %d\n", rc);
- GOTO(out_rename_srcput, rc = -EIO);
- }
- } else
- ldlm_lock_dump((void *)(unsigned long)srclockh.addr);
-
- de_tgtdir = mds_fid2dentry(mds, rec->ur_fid2, NULL);
- if (IS_ERR(de_tgtdir))
- GOTO(out_rename_srcdir, rc = -ESTALE);
-
- lock_mode = (req->rq_reqmsg->opc == MDS_REINT) ? LCK_PW : LCK_PW;
- res_id[0] = de_tgtdir->d_inode->i_ino;
- res_id[1] = de_tgtdir->d_inode->i_generation;
-
- rc = ldlm_lock_match(obd->obd_namespace, res_id, LDLM_PLAIN,
- NULL, 0, lock_mode, &tgtlockh);
- if (rc == 0) {
- flags = 0;
- LDLM_DEBUG_NOLOCK("enqueue res "LPU64, res_id[0]);
- rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, NULL,
- res_id, LDLM_PLAIN, NULL, 0, lock_mode,
- &flags, ldlm_completion_ast,
- mds_blocking_ast, NULL, 0, &tgtlockh);
- if (rc != ELDLM_OK) {
- CERROR("lock enqueue: err: %d\n", rc);
- GOTO(out_rename_tgtput, rc = -EIO);
- }
- } else
- ldlm_lock_dump((void *)(unsigned long)tgtlockh.addr);
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- double_lock(de_tgtdir, de_srcdir);
-#endif
- de_old = lookup_one_len(rec->ur_name, de_srcdir, rec->ur_namelen - 1);
- if (IS_ERR(de_old)) {
- CERROR("old child lookup error (%*s): %ld\n",
- rec->ur_namelen - 1, rec->ur_name, PTR_ERR(de_old));
- GOTO(out_rename_tgtdir, rc = -ENOENT);
- }
-
- de_new = lookup_one_len(rec->ur_tgt, de_tgtdir, rec->ur_tgtlen - 1);
- if (IS_ERR(de_new)) {
- CERROR("new child lookup error (%*s): %ld\n",
- rec->ur_tgtlen - 1, rec->ur_tgt, PTR_ERR(de_new));
- GOTO(out_rename_deold, rc = -ENOENT);
- }
-
- /* in intent case ship back attributes to client */
- if (offset) {
- struct mds_body *body = lustre_msg_buf(req->rq_repmsg, 1);
- struct inode *inode = de_new->d_inode;
-
- if (!inode) {
- body->valid = 0;
- } else {
- mds_pack_inode2fid(&body->fid1, inode);
- mds_pack_inode2body(body, inode);
- if (S_ISREG(inode->i_mode))
- mds_pack_md(mds, req, 2, body, inode);
- }
- }
-
- OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_RENAME_WRITE,
- to_kdev_t(de_srcdir->d_inode->i_sb->s_dev));
-
- mds_start_transno(mds);
- handle = mds_fs_start(mds, de_tgtdir->d_inode, MDS_FSOP_RENAME);
- if (IS_ERR(handle)) {
- rc = PTR_ERR(handle);
- mds_finish_transno(mds, handle, req, rc);
- GOTO(out_rename_denew, rc);
- }
-
- lock_kernel();
- rc = vfs_rename(de_srcdir->d_inode, de_old, de_tgtdir->d_inode, de_new,
- NULL);
- unlock_kernel();
-
- rc = mds_finish_transno(mds, handle, req, rc);
-
- err = mds_fs_commit(mds, de_tgtdir->d_inode, handle);
- if (err) {
- CERROR("error on commit: err = %d\n", err);
- if (!rc)
- rc = err;
- }
- EXIT;
-
-out_rename_denew:
- l_dput(de_new);
-out_rename_deold:
- if (!rc) {
- res_id[0] = de_old->d_inode->i_ino;
- res_id[1] = de_old->d_inode->i_generation;
- flags = 0;
- /* Take an exclusive lock on the resource that we're
- * about to free, to force everyone to drop their
- * locks. */
- LDLM_DEBUG_NOLOCK("getting EX lock res "LPU64, res_id[0]);
- rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace, NULL,
- res_id, LDLM_PLAIN, NULL, 0, LCK_EX,
- &flags, ldlm_completion_ast,
- mds_blocking_ast, NULL, 0, &oldhandle);
- if (rc)
- CERROR("failed to get child inode lock (child ino "
- LPD64" dir ino %ld)\n",
- res_id[0], de_old->d_inode->i_ino);
- }
-
- l_dput(de_old);
-
- if (!rc) {
- ldlm_lock_decref(&oldhandle, LCK_EX);
- rc = ldlm_cli_cancel(&oldhandle);
- if (rc < 0)
- CERROR("failed to cancel child inode lock ino "
- LPD64": %d\n", res_id[0], rc);
- }
-out_rename_tgtdir:
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- double_up(&de_srcdir->d_inode->i_sem, &de_tgtdir->d_inode->i_sem);
-#endif
- ldlm_lock_decref(&tgtlockh, lock_mode);
-out_rename_tgtput:
- l_dput(de_tgtdir);
-out_rename_srcdir:
- ldlm_lock_decref(&srclockh, lock_mode);
-out_rename_srcput:
- l_dput(de_srcdir);
-out_rename:
- req->rq_status = rc;
- return 0;
-}
-
-typedef int (*mds_reinter) (struct mds_update_record *, int offset,
- struct ptlrpc_request *);
-
-static mds_reinter reinters[REINT_MAX + 1] = {
- [REINT_SETATTR] mds_reint_setattr,
- [REINT_CREATE] mds_reint_create,
- [REINT_UNLINK] mds_reint_unlink,
- [REINT_LINK] mds_reint_link,
- [REINT_RENAME] mds_reint_rename,
-};
-
-int mds_reint_rec(struct mds_update_record *rec, int offset,
- struct ptlrpc_request *req)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct obd_run_ctxt saved;
- struct obd_ucred uc;
- int realop = rec->ur_opcode & REINT_OPCODE_MASK;
- int rc;
-
- if (realop < 1 || realop > REINT_MAX) {
- CERROR("opcode %d not valid (%sREPLAYING)\n", realop,
- rec->ur_opcode & REINT_REPLAYING ? "" : "not ");
- rc = req->rq_status = -EINVAL;
- RETURN(rc);
- }
-
- uc.ouc_fsuid = rec->ur_fsuid;
- uc.ouc_fsgid = rec->ur_fsgid;
- uc.ouc_cap = rec->ur_cap;
-
- push_ctxt(&saved, &mds->mds_ctxt, &uc);
- rc = reinters[realop] (rec, offset, req);
- pop_ctxt(&saved, &mds->mds_ctxt, &uc);
-
- return rc;
-}
+++ /dev/null
-#! /bin/sh
-# Common stub for a few missing GNU programs while installing.
-# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc.
-# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
-
-# 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, 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.
-
-if test $# -eq 0; then
- echo 1>&2 "Try \`$0 --help' for more information"
- exit 1
-fi
-
-run=:
-
-# In the cases where this matters, `missing' is being run in the
-# srcdir already.
-if test -f configure.ac; then
- configure_ac=configure.ac
-else
- configure_ac=configure.in
-fi
-
-case "$1" in
---run)
- # Try to run requested program, and just exit if it succeeds.
- run=
- shift
- "$@" && exit 0
- ;;
-esac
-
-# If it does not exist, or fails to run (possibly an outdated version),
-# try to emulate it.
-case "$1" in
-
- -h|--h|--he|--hel|--help)
- echo "\
-$0 [OPTION]... PROGRAM [ARGUMENT]...
-
-Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
-error status if there is no known handling for PROGRAM.
-
-Options:
- -h, --help display this help and exit
- -v, --version output version information and exit
- --run try to run the given command, and emulate it if it fails
-
-Supported PROGRAM values:
- aclocal touch file \`aclocal.m4'
- autoconf touch file \`configure'
- autoheader touch file \`config.h.in'
- automake touch all \`Makefile.in' files
- bison create \`y.tab.[ch]', if possible, from existing .[ch]
- flex create \`lex.yy.c', if possible, from existing .c
- help2man touch the output file
- lex create \`lex.yy.c', if possible, from existing .c
- makeinfo touch the output file
- tar try tar, gnutar, gtar, then tar without non-portable flags
- yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
- ;;
-
- -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
- echo "missing 0.4 - GNU automake"
- ;;
-
- -*)
- echo 1>&2 "$0: Unknown \`$1' option"
- echo 1>&2 "Try \`$0 --help' for more information"
- exit 1
- ;;
-
- aclocal*)
- if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
- # We have it, but it failed.
- exit 1
- fi
-
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified \`acinclude.m4' or \`${configure_ac}'. You might want
- to install the \`Automake' and \`Perl' packages. Grab them from
- any GNU archive site."
- touch aclocal.m4
- ;;
-
- autoconf)
- if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
- # We have it, but it failed.
- exit 1
- fi
-
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified \`${configure_ac}'. You might want to install the
- \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
- archive site."
- touch configure
- ;;
-
- autoheader)
- if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
- # We have it, but it failed.
- exit 1
- fi
-
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified \`acconfig.h' or \`${configure_ac}'. You might want
- to install the \`Autoconf' and \`GNU m4' packages. Grab them
- from any GNU archive site."
- files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
- test -z "$files" && files="config.h"
- touch_files=
- for f in $files; do
- case "$f" in
- *:*) touch_files="$touch_files "`echo "$f" |
- sed -e 's/^[^:]*://' -e 's/:.*//'`;;
- *) touch_files="$touch_files $f.in";;
- esac
- done
- touch $touch_files
- ;;
-
- automake*)
- if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
- # We have it, but it failed.
- exit 1
- fi
-
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
- You might want to install the \`Automake' and \`Perl' packages.
- Grab them from any GNU archive site."
- find . -type f -name Makefile.am -print |
- sed 's/\.am$/.in/' |
- while read f; do touch "$f"; done
- ;;
-
- autom4te)
- if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
- # We have it, but it failed.
- exit 1
- fi
-
- echo 1>&2 "\
-WARNING: \`$1' is needed, and you do not seem to have it handy on your
- system. You might have modified some files without having the
- proper tools for further handling them.
- You can get \`$1Help2man' as part of \`Autoconf' from any GNU
- archive site."
-
- file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
- test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
- if test -f "$file"; then
- touch $file
- else
- test -z "$file" || exec >$file
- echo "#! /bin/sh"
- echo "# Created by GNU Automake missing as a replacement of"
- echo "# $ $@"
- echo "exit 0"
- chmod +x $file
- exit 1
- fi
- ;;
-
- bison|yacc)
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified a \`.y' file. You may need the \`Bison' package
- in order for those modifications to take effect. You can get
- \`Bison' from any GNU archive site."
- rm -f y.tab.c y.tab.h
- if [ $# -ne 1 ]; then
- eval LASTARG="\${$#}"
- case "$LASTARG" in
- *.y)
- SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" y.tab.c
- fi
- SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" y.tab.h
- fi
- ;;
- esac
- fi
- if [ ! -f y.tab.h ]; then
- echo >y.tab.h
- fi
- if [ ! -f y.tab.c ]; then
- echo 'main() { return 0; }' >y.tab.c
- fi
- ;;
-
- lex|flex)
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified a \`.l' file. You may need the \`Flex' package
- in order for those modifications to take effect. You can get
- \`Flex' from any GNU archive site."
- rm -f lex.yy.c
- if [ $# -ne 1 ]; then
- eval LASTARG="\${$#}"
- case "$LASTARG" in
- *.l)
- SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
- if [ -f "$SRCFILE" ]; then
- cp "$SRCFILE" lex.yy.c
- fi
- ;;
- esac
- fi
- if [ ! -f lex.yy.c ]; then
- echo 'main() { return 0; }' >lex.yy.c
- fi
- ;;
-
- help2man)
- if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
- # We have it, but it failed.
- exit 1
- fi
-
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified a dependency of a manual page. You may need the
- \`Help2man' package in order for those modifications to take
- effect. You can get \`Help2man' from any GNU archive site."
-
- file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
- if test -z "$file"; then
- file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
- fi
- if [ -f "$file" ]; then
- touch $file
- else
- test -z "$file" || exec >$file
- echo ".ab help2man is required to generate this page"
- exit 1
- fi
- ;;
-
- makeinfo)
- if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
- # We have makeinfo, but it failed.
- exit 1
- fi
-
- echo 1>&2 "\
-WARNING: \`$1' is missing on your system. You should only need it if
- you modified a \`.texi' or \`.texinfo' file, or any other file
- indirectly affecting the aspect of the manual. The spurious
- call might also be the consequence of using a buggy \`make' (AIX,
- DU, IRIX). You might want to install the \`Texinfo' package or
- the \`GNU make' package. Grab either from any GNU archive site."
- file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
- if test -z "$file"; then
- file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
- file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
- fi
- touch $file
- ;;
-
- tar)
- shift
- if test -n "$run"; then
- echo 1>&2 "ERROR: \`tar' requires --run"
- exit 1
- fi
-
- # We have already tried tar in the generic part.
- # Look for gnutar/gtar before invocation to avoid ugly error
- # messages.
- if (gnutar --version > /dev/null 2>&1); then
- gnutar "$@" && exit 0
- fi
- if (gtar --version > /dev/null 2>&1); then
- gtar "$@" && exit 0
- fi
- firstarg="$1"
- if shift; then
- case "$firstarg" in
- *o*)
- firstarg=`echo "$firstarg" | sed s/o//`
- tar "$firstarg" "$@" && exit 0
- ;;
- esac
- case "$firstarg" in
- *h*)
- firstarg=`echo "$firstarg" | sed s/h//`
- tar "$firstarg" "$@" && exit 0
- ;;
- esac
- fi
-
- echo 1>&2 "\
-WARNING: I can't seem to be able to run \`tar' with the given arguments.
- You may want to install GNU tar or Free paxutils, or check the
- command line arguments."
- exit 1
- ;;
-
- *)
- echo 1>&2 "\
-WARNING: \`$1' is needed, and you do not seem to have it handy on your
- system. You might have modified some files without having the
- proper tools for further handling them. Check the \`README' file,
- it often tells you about the needed prerequirements for installing
- this package. You may also peek at any GNU archive site, in case
- some other package would contain this missing \`$1' program."
- exit 1
- ;;
-esac
-
-exit 0
+++ /dev/null
-#! /bin/sh
-# mkinstalldirs --- make directory hierarchy
-# Author: Noah Friedman <friedman@prep.ai.mit.edu>
-# Created: 1993-05-16
-# Public domain
-
-# $Id: mkinstalldirs,v 1.1 2002/05/27 16:48:11 pschwan Exp $
-
-errstatus=0
-
-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
- fi
- fi
-
- pathcomp="$pathcomp/"
- done
-done
-
-exit $errstatus
-
-# mkinstalldirs ends here
+++ /dev/null
-obd-*/obd-*
-CVS
-*~
-make.rules
-config.*
-*.o
-*.orig
-*.backup
-.depfiles
-ext2obd/dir.c
-ext2obd/file.c
-ext2obd/ialloc.c
-ext2obd/inode.c
-ext2obd/super.c
-ext2obd/fsync.c
-ext2obd/ioctl.c
-ext2obd/balloc.c
-ext2obd/acl.c
-ext2obd/namei.c
-ext2obd/symlink.c
-ext2obd/bitmap.c
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
-# FIXME: we need to make it clear that obdclass.o depends on
-# lustre_build_version, or 'make -j2' breaks!
-DEFS=
-MODULE = obdclass
-modulefs_DATA = lustre_build_version obdclass.o
-EXTRA_PROGRAMS = obdclass
-obdclass_SOURCES = debug.c genops.c class_obd.c sysctl.c uuid.c lprocfs_status.c
-include $(top_srcdir)/Rules
-lustre_build_version:
- perl $(top_srcdir)/scripts/version_tag.pl $(top_srcdir) > tmpver
- diff -u $(top_builddir)/include/linux/lustre_build_version.h tmpver \
- 2> /dev/null &&\
- $(RM) tmpver || \
- mv tmpver $(top_builddir)/include/linux/lustre_build_version.h
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * These are the only exported functions, they provide some generic
- * infrastructure for managing object devices
- *
- * Object Devices Class Driver
- */
-
-#define EXPORT_SYMTAB
-#include <linux/config.h> /* for CONFIG_PROC_FS */
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/lp.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/delay.h>
-#include <linux/skbuff.h>
-#include <linux/proc_fs.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/highmem.h>
-#include <asm/io.h>
-#include <asm/ioctls.h>
-#include <asm/system.h>
-#include <asm/poll.h>
-#include <asm/uaccess.h>
-#include <linux/miscdevice.h>
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_debug.h>
-#include <linux/smp_lock.h>
-#include <linux/lprocfs_status.h>
-#include <portals/lib-types.h> /* for PTL_MD_MAX_IOV */
-#include <linux/lustre_build_version.h>
-
-struct semaphore obd_conf_sem; /* serialize configuration commands */
-struct obd_device obd_dev[MAX_OBD_DEVICES];
-struct list_head obd_types;
-unsigned long obd_memory;
-
-/* The following are visible and mutable through /proc/sys/lustre/. */
-unsigned long obd_fail_loc;
-unsigned long obd_timeout = 100;
-char obd_recovery_upcall[128] = "/usr/lib/lustre/ha_assist";
-
-extern struct obd_type *class_nm_to_type(char *nm);
-
-/* opening /dev/obd */
-static int obd_class_open(struct inode * inode, struct file * file)
-{
- ENTRY;
-
- file->private_data = NULL;
- CDEBUG(D_IOCTL, "MOD_INC_USE for open: count = %d\n",
- atomic_read(&(THIS_MODULE)->uc.usecount));
- MOD_INC_USE_COUNT;
- RETURN(0);
-}
-
-/* closing /dev/obd */
-static int obd_class_release(struct inode * inode, struct file * file)
-{
- ENTRY;
-
- // XXX drop lsm, connections here
- if (file->private_data)
- file->private_data = NULL;
-
- CDEBUG(D_IOCTL, "MOD_DEC_USE for close: count = %d\n",
- atomic_read(&(THIS_MODULE)->uc.usecount) - 1);
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-static inline void obd_data2conn(struct lustre_handle *conn,
- struct obd_ioctl_data *data)
-{
- conn->addr = data->ioc_addr;
- conn->cookie = data->ioc_cookie;
-}
-
-static inline void obd_conn2data(struct obd_ioctl_data *data,
- struct lustre_handle *conn)
-{
- data->ioc_addr = conn->addr;
- data->ioc_cookie = conn->cookie;
-}
-
-static void forcibly_detach_exports(struct obd_device *obd)
-{
- int rc;
- struct list_head *tmp, *n;
- struct lustre_handle fake_conn;
-
- CDEBUG(D_IOCTL, "OBD device %d (%p) has exports, "
- "disconnecting them", obd->obd_minor, obd);
- list_for_each_safe(tmp, n, &obd->obd_exports) {
- struct obd_export *exp = list_entry(tmp, struct obd_export,
- exp_obd_chain);
- fake_conn.addr = (__u64)(unsigned long)exp;
- fake_conn.cookie = exp->exp_cookie;
- rc = obd_disconnect(&fake_conn);
- if (rc) {
- CDEBUG(D_IOCTL, "disconnecting export %p failed: %d\n",
- exp, rc);
- } else {
- CDEBUG(D_IOCTL, "export %p disconnected\n", exp);
- }
- }
-}
-
-/* to control /dev/obd */
-static int obd_class_ioctl (struct inode * inode, struct file * filp,
- unsigned int cmd, unsigned long arg)
-{
- char *buf = NULL;
- struct obd_ioctl_data *data;
- struct obd_device *obd = filp->private_data;
- struct lustre_handle conn;
- int err = 0, len = 0, serialised = 0;
- ENTRY;
-
- switch (cmd) {
- case OBD_IOC_BRW_WRITE:
- case OBD_IOC_BRW_READ:
- case OBD_IOC_GETATTR:
- break;
- default:
- down(&obd_conf_sem);
- serialised = 1;
- break;
- }
-
- if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS &&
- cmd != OBD_IOC_LIST && cmd != OBD_GET_VERSION &&
- cmd != OBD_IOC_NAME2DEV && cmd != OBD_IOC_NEWDEV) {
- CERROR("OBD ioctl: No device\n");
- GOTO(out, err = -EINVAL);
- }
- if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
- CERROR("OBD ioctl: data error\n");
- GOTO(out, err = -EINVAL);
- }
- data = (struct obd_ioctl_data *)buf;
-
- switch (cmd) {
- case TCGETS:
- GOTO(out, err=-EINVAL);
- case OBD_IOC_DEVICE: {
- CDEBUG(D_IOCTL, "\n");
- if (data->ioc_dev >= MAX_OBD_DEVICES || data->ioc_dev < 0) {
- CERROR("OBD ioctl: DEVICE insufficient devices\n");
- GOTO(out, err=-EINVAL);
- }
- CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev);
-
- filp->private_data = &obd_dev[data->ioc_dev];
- GOTO(out, err=0);
- }
-
- case OBD_IOC_LIST: {
- int i;
- char *buf2 = data->ioc_bulk;
- int remains = data->ioc_inllen1;
-
- if (!data->ioc_inlbuf1) {
- CERROR("No buffer passed!\n");
- GOTO(out, err=-EINVAL);
- }
-
-
- for (i = 0 ; i < MAX_OBD_DEVICES ; i++) {
- int l;
- char *status;
- struct obd_device *obd = &obd_dev[i];
- if (!obd->obd_type)
- continue;
- if (obd->obd_flags & OBD_SET_UP)
- status = "UP";
- else if (obd->obd_flags & OBD_ATTACHED)
- status = "AT";
- else
- status = "-";
- l = snprintf(buf2, remains, "%2d %s %s %s %s %d\n",
- i, status, obd->obd_type->typ_name,
- obd->obd_name, obd->obd_uuid, obd->obd_type->typ_refcnt);
- buf2 +=l;
- remains -=l;
- if (remains <= 0) {
- CERROR("not enough space for device listing\n");
- break;
- }
- }
-
- err = copy_to_user((void *)arg, data, len);
- if (err)
- err = -EFAULT;
- GOTO(out, err);
- }
-
- case OBD_GET_VERSION:
- if (!data->ioc_inlbuf1) {
- CERROR("No buffer passed in ioctl\n");
- GOTO(out, err = -EINVAL);
- }
-
- if (strlen(BUILD_VERSION) + 1 > data->ioc_inllen1) {
- CERROR("ioctl buffer too small to hold version\n");
- GOTO(out, err = -EINVAL);
- }
-
- memcpy(data->ioc_bulk, BUILD_VERSION,
- strlen(BUILD_VERSION) + 1);
-
- err = copy_to_user((void *)arg, data, len);
- if (err)
- err = -EFAULT;
- GOTO(out, err);
-
- case OBD_IOC_NAME2DEV: {
- /* Resolve a device name. This does not change the
- * currently selected device.
- */
- int dev;
-
- if (!data->ioc_inllen1 || !data->ioc_inlbuf1 ) {
- CERROR("No name passed,!\n");
- GOTO(out, err=-EINVAL);
- }
- if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
- CERROR("Name not nul terminated!\n");
- GOTO(out, err=-EINVAL);
- }
-
- CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
- dev = class_name2dev(data->ioc_inlbuf1);
- data->ioc_dev = dev;
- if (dev == -1) {
- CDEBUG(D_IOCTL, "No device for name %s!\n",
- data->ioc_inlbuf1);
- GOTO(out, err=-EINVAL);
- }
-
- CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
- dev);
- err = copy_to_user((void *)arg, data, sizeof(*data));
- if (err)
- err = -EFAULT;
- GOTO(out, err);
- }
-
- case OBD_IOC_UUID2DEV: {
- /* Resolve a device uuid. This does not change the
- * currently selected device.
- */
- int dev;
-
- if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
- CERROR("No UUID passed!\n");
- GOTO(out, err=-EINVAL);
- }
- if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
- CERROR("Name not nul terminated!\n");
- GOTO(out, err=-EINVAL);
- }
-
- CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
- dev = class_uuid2dev(data->ioc_inlbuf1);
- data->ioc_dev = dev;
- if (dev == -1) {
- CDEBUG(D_IOCTL, "No device for name %s!\n",
- data->ioc_inlbuf1);
- GOTO(out, err=-EINVAL);
- }
-
- CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
- dev);
- err = copy_to_user((void *)arg, data, sizeof(*data));
- if (err)
- err = -EFAULT;
- GOTO(out, err);
- }
-
- case OBD_IOC_NEWDEV: {
- int dev = -1;
- int i;
-
- filp->private_data = NULL;
- for (i = 0 ; i < MAX_OBD_DEVICES ; i++) {
- struct obd_device *obd = &obd_dev[i];
- if (!obd->obd_type) {
- filp->private_data = obd;
- dev = i;
- break;
- }
- }
-
-
- data->ioc_dev = dev;
- if (dev == -1)
- GOTO(out, err=-EINVAL);
-
- err = copy_to_user((void *)arg, data, sizeof(*data));
- if (err)
- err = -EFAULT;
- GOTO(out, err);
- }
-
- case OBD_IOC_ATTACH: {
- struct obd_type *type;
- int minor;
-
- /* have we attached a type to this device */
- if (obd->obd_flags & OBD_ATTACHED || obd->obd_type) {
- CERROR("OBD: Device %d already typed as %s.\n",
- obd->obd_minor, MKSTR(obd->obd_type->typ_name));
- GOTO(out, err=-EBUSY);
- }
-
- if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
- CERROR("No type passed!\n");
- GOTO(out, err=-EINVAL);
- }
- if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
- CERROR("Type not nul terminated!\n");
- GOTO(out, err=-EINVAL);
- }
-
- CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
- MKSTR(data->ioc_inlbuf1),
- MKSTR(data->ioc_inlbuf2), MKSTR(data->ioc_inlbuf3));
-
- /* find the type */
- type = class_nm_to_type(data->ioc_inlbuf1);
- if (!type) {
- CERROR("OBD: unknown type dev %d\n", obd->obd_minor);
- GOTO(out, err=-EINVAL);
- }
-
- minor = obd->obd_minor;
- memset(obd, 0, sizeof(*obd));
- obd->obd_minor = minor;
- obd->obd_type = type;
- INIT_LIST_HEAD(&obd->obd_exports);
- INIT_LIST_HEAD(&obd->obd_imports);
- spin_lock_init(&obd->obd_dev_lock);
-
- if (data->ioc_inlbuf2) {
- int len = strlen(data->ioc_inlbuf2) + 1;
- OBD_ALLOC(obd->obd_name, len);
- if (!obd->obd_name) {
- CERROR("no memory\n");
- LBUG();
- }
- memcpy(obd->obd_name, data->ioc_inlbuf2, len);
- } else {
- CERROR("WARNING: unnamed obd device\n");
- }
- if (data->ioc_inlbuf3) {
- int len = strlen(data->ioc_inlbuf3);
- if (len >= sizeof(obd->obd_uuid)) {
- CERROR("uuid must be < %d bytes long\n",
- sizeof(obd->obd_uuid));
- if (obd->obd_name)
- OBD_FREE(obd->obd_name,
- strlen(obd->obd_name) + 1);
- GOTO(out, err=-EINVAL);
- }
- memcpy(obd->obd_uuid, data->ioc_inlbuf3, len);
- }
- /* do the attach */
- if (OBP(obd, attach))
- err = OBP(obd,attach)(obd, sizeof(*data), data);
- if (err) {
- if(data->ioc_inlbuf2)
- OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
- obd->obd_type = NULL;
- } else {
- obd->obd_flags |= OBD_ATTACHED;
-
- type->typ_refcnt++;
- CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n",
- obd->obd_minor, data->ioc_inlbuf1);
-
- CDEBUG(D_IOCTL, "MOD_INC_USE for attach: count = %d\n",
- atomic_read(&(THIS_MODULE)->uc.usecount));
- MOD_INC_USE_COUNT;
- }
-
- GOTO(out, err);
- }
-
- case OBD_IOC_DETACH: {
- ENTRY;
- if (obd->obd_flags & OBD_SET_UP) {
- CERROR("OBD device %d still set up\n", obd->obd_minor);
- GOTO(out, err=-EBUSY);
- }
- if (!(obd->obd_flags & OBD_ATTACHED) ) {
- CERROR("OBD device %d not attached\n", obd->obd_minor);
- GOTO(out, err=-ENODEV);
- }
- if (!list_empty(&obd->obd_exports)) {
- if (!data->ioc_inlbuf1 || data->ioc_inlbuf1[0] != 'F') {
- CERROR("OBD device %d (%p) has exports\n",
- obd->obd_minor, obd);
- GOTO(out, err=-EBUSY);
- }
- forcibly_detach_exports(obd);
- }
- if (OBP(obd, detach))
- err=OBP(obd,detach)(obd);
-
- if (obd->obd_name) {
- OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
- obd->obd_name = NULL;
- }
-
- obd->obd_flags &= ~OBD_ATTACHED;
- obd->obd_type->typ_refcnt--;
- obd->obd_type = NULL;
- CDEBUG(D_IOCTL, "MOD_DEC_USE for detach: count = %d\n",
- atomic_read(&(THIS_MODULE)->uc.usecount) - 1);
- MOD_DEC_USE_COUNT;
- GOTO(out, err = 0);
- }
-
- case OBD_IOC_SETUP: {
- /* have we attached a type to this device? */
- if (!(obd->obd_flags & OBD_ATTACHED)) {
- CERROR("Device %d not attached\n", obd->obd_minor);
- GOTO(out, err=-ENODEV);
- }
-
- /* has this been done already? */
- if ( obd->obd_flags & OBD_SET_UP ) {
- CERROR("Device %d already setup (type %s)\n",
- obd->obd_minor, obd->obd_type->typ_name);
- GOTO(out, err=-EBUSY);
- }
-
- if ( OBT(obd) && OBP(obd, setup) )
- err = obd_setup(obd, sizeof(*data), data);
-
- if (!err) {
- obd->obd_type->typ_refcnt++;
- obd->obd_flags |= OBD_SET_UP;
- }
-
- GOTO(out, err);
- }
- case OBD_IOC_CLEANUP: {
- /* have we attached a type to this device? */
- if (!(obd->obd_flags & OBD_ATTACHED)) {
- CERROR("Device %d not attached\n", obd->obd_minor);
- GOTO(out, err=-ENODEV);
- }
-
- if ( OBT(obd) && OBP(obd, cleanup) )
- err = obd_cleanup(obd);
-
- if (!err) {
- obd->obd_flags &= ~OBD_SET_UP;
- obd->obd_type->typ_refcnt--;
- }
- GOTO(out, err);
- }
-
- case OBD_IOC_CONNECT: {
- char * cluuid = "OBD_CLASS_UUID";
- obd_data2conn(&conn, data);
-
- err = obd_connect(&conn, obd, cluuid, NULL, NULL);
-
- CDEBUG(D_IOCTL, "assigned export "LPX64"\n", conn.addr);
- obd_conn2data(data, &conn);
- if (err)
- GOTO(out, err);
-
- err = copy_to_user((void *)arg, data, sizeof(*data));
- if (err)
- err = -EFAULT;
- // XXX save connection data into file handle
- GOTO(out, err);
- }
-
- case OBD_IOC_DISCONNECT: {
- obd_data2conn(&conn, data);
- err = obd_disconnect(&conn);
- GOTO(out, err);
- }
-
- case OBD_IOC_DEC_USE_COUNT: {
- CDEBUG(D_IOCTL, "MOD_DEC_USE for force dec: count = %d\n",
- atomic_read(&(THIS_MODULE)->uc.usecount) - 1);
- MOD_DEC_USE_COUNT;
- GOTO(out, err=0);
- }
-
- default:
- obd_data2conn(&conn, data);
-
- err = obd_iocontrol(cmd, &conn, len, data, NULL);
- if (err)
- GOTO(out, err);
-
- err = copy_to_user((void *)arg, data, len);
- if (err)
- err = -EFAULT;
- GOTO(out, err);
- }
-
- out:
- if (buf)
- OBD_FREE(buf, len);
- if (serialised)
- up(&obd_conf_sem);
- RETURN(err);
-} /* obd_class_ioctl */
-
-
-
-/* declare character device */
-static struct file_operations obd_psdev_fops = {
- ioctl: obd_class_ioctl, /* ioctl */
- open: obd_class_open, /* open */
- release: obd_class_release, /* release */
-};
-
-/* modules setup */
-#define OBD_MINOR 241
-static struct miscdevice obd_psdev = {
- OBD_MINOR,
- "obd_psdev",
- &obd_psdev_fops
-};
-
-void (*class_signal_connection_failure)(struct ptlrpc_connection *);
-
-#ifdef CONFIG_HIGHMEM
-/* Allow at most 3/4 of the kmap mappings to be consumed by vector I/O
- * requests. This avoids deadlocks on servers which have a lot of clients
- * doing vector I/O. We don't need to do this for non-vector I/O requests
- * because singleton requests will just block on the kmap itself and never
- * deadlock waiting for additional kmaps to complete.
- *
- * If we are a "server" task, we can have at most a single reservation
- * in excess of the maximum. This avoids a deadlock when multiple client
- * threads are on the same machine as the server threads, and the clients
- * have consumed all of the available mappings. As long as a single server
- * thread is can make progress, we are guaranteed to avoid deadlock.
- */
-#define OBD_KMAP_MAX (LAST_PKMAP * 3 / 4)
-static atomic_t obd_kmap_count = ATOMIC_INIT(OBD_KMAP_MAX);
-static DECLARE_WAIT_QUEUE_HEAD(obd_kmap_waitq);
-
-void obd_kmap_get(int count, int server)
-{
- //CERROR("getting %d kmap counts (%d/%d)\n", count,
- // atomic_read(&obd_kmap_count), OBD_KMAP_MAX);
- if (count == 1)
- atomic_dec(&obd_kmap_count);
- else while (atomic_add_negative(-count, &obd_kmap_count)) {
- static long next_show = 0;
- static int skipped = 0;
-
- if (server && atomic_read(&obd_kmap_count) >= -PTL_MD_MAX_IOV)
- break;
-
- CDEBUG(D_OTHER, "negative kmap reserved count: %d\n",
- atomic_read(&obd_kmap_count));
- atomic_add(count, &obd_kmap_count);
-
- if (time_after(jiffies, next_show)) {
- CERROR("blocking %s (and %d others) for kmaps\n",
- current->comm, skipped);
- next_show = jiffies + 5*HZ;
- skipped = 0;
- } else
- skipped++;
- wait_event(obd_kmap_waitq,
- atomic_read(&obd_kmap_count) >= count);
- }
-}
-
-void obd_kmap_put(int count)
-{
- atomic_add(count, &obd_kmap_count);
- /* Wake up sleepers. Sadly, this wakes up all of the tasks at once.
- * We could have something smarter here like:
- while (atomic_read(&obd_kmap_count) > 0)
- wake_up_nr(obd_kmap_waitq, 1);
- although we would need to set somewhere (probably obd_class_init):
- obd_kmap_waitq.flags |= WQ_FLAG_EXCLUSIVE;
- For now the wait_event() condition will handle this OK I believe.
- */
- if (atomic_read(&obd_kmap_count) > 0)
- wake_up(&obd_kmap_waitq);
-}
-
-EXPORT_SYMBOL(obd_kmap_get);
-EXPORT_SYMBOL(obd_kmap_put);
-#endif
-
-EXPORT_SYMBOL(obd_dev);
-EXPORT_SYMBOL(obdo_cachep);
-EXPORT_SYMBOL(obd_memory);
-EXPORT_SYMBOL(obd_fail_loc);
-EXPORT_SYMBOL(obd_timeout);
-EXPORT_SYMBOL(obd_recovery_upcall);
-EXPORT_SYMBOL(ptlrpc_put_connection_superhack);
-
-EXPORT_SYMBOL(class_register_type);
-EXPORT_SYMBOL(class_unregister_type);
-EXPORT_SYMBOL(class_name2dev);
-EXPORT_SYMBOL(class_uuid2dev);
-EXPORT_SYMBOL(class_uuid2obd);
-EXPORT_SYMBOL(class_new_export);
-EXPORT_SYMBOL(class_destroy_export);
-EXPORT_SYMBOL(class_connect);
-EXPORT_SYMBOL(class_conn2export);
-EXPORT_SYMBOL(class_conn2obd);
-EXPORT_SYMBOL(class_conn2cliimp);
-EXPORT_SYMBOL(class_conn2ldlmimp);
-EXPORT_SYMBOL(class_disconnect);
-EXPORT_SYMBOL(class_disconnect_all);
-EXPORT_SYMBOL(class_uuid_unparse);
-
-EXPORT_SYMBOL(class_signal_connection_failure);
-EXPORT_SYMBOL(class_nm_to_type);
-
-static int __init init_obdclass(void)
-{
- struct obd_device *obd;
- int err;
- int i;
-
- printk(KERN_INFO "OBD class driver Build Version: " BUILD_VERSION
- ", info@clusterfs.com\n");
-
- sema_init(&obd_conf_sem, 1);
- INIT_LIST_HEAD(&obd_types);
-
- if ((err = misc_register(&obd_psdev))) {
- CERROR("cannot register %d err %d\n", OBD_MINOR, err);
- return err;
- }
-
- /* This struct is already zerod for us (static global) */
- for (i = 0, obd = obd_dev; i < MAX_OBD_DEVICES; i++, obd++)
- obd->obd_minor = i;
-
- err = obd_init_caches();
-
- if (err)
- return err;
- obd_sysctl_init();
-
- err = lprocfs_reg_main();
-
- return 0;
-}
-
-static void __exit cleanup_obdclass(void)
-{
- int i, err;
- ENTRY;
-
- misc_deregister(&obd_psdev);
- for (i = 0; i < MAX_OBD_DEVICES; i++) {
- struct obd_device *obd = &obd_dev[i];
- if (obd->obd_type && (obd->obd_flags & OBD_SET_UP) &&
- OBT(obd) && OBP(obd, detach)) {
- /* XXX should this call generic detach otherwise? */
- OBP(obd, detach)(obd);
- }
- }
-
- obd_cleanup_caches();
- obd_sysctl_clean();
-
- err = lprocfs_dereg_main();
-
- CERROR("obd memory leaked: %ld bytes\n", obd_memory);
- EXIT;
-}
-
-/* Check that we're building against the appropriate version of the Lustre
- * kernel patch */
-#include <linux/lustre_version.h>
-#if (LUSTRE_KERNEL_VERSION != 3)
-# error Cannot continue: Your Lustre kernel patch is out of date
-#endif
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Class Driver Build Version: " BUILD_VERSION);
-MODULE_LICENSE("GPL");
-
-module_init(init_obdclass);
-module_exit(cleanup_obdclass);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Helper routines for dumping data structs for debugging.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copryright (C) 2002 Cluster File Systems, Inc.
- *
- */
-
-#define DEBUG_SUBSYSTEM D_OTHER
-
-#define EXPORT_SYMTAB
-#include <linux/obd_ost.h>
-#include <linux/lustre_debug.h>
-#include <linux/lustre_net.h>
-
-int dump_ioo(struct obd_ioobj *ioo)
-{
- CERROR("obd_ioobj: ioo_id="LPD64", ioo_gr="LPD64", ioo_type=%d, ioo_bufct=%d\n",
- ioo->ioo_id, ioo->ioo_gr, ioo->ioo_type, ioo->ioo_bufcnt);
- return -EINVAL;
-}
-
-int dump_lniobuf(struct niobuf_local *nb)
-{
- CERROR("niobuf_local: addr=%p, offset="LPD64", len=%d, xid=%d, page=%p\n",
- nb->addr, nb->offset, nb->len, nb->xid, nb->page);
- CERROR("nb->page: index = %ld\n", nb->page ? nb->page->index : -1);
-
- return -EINVAL;
-}
-
-int dump_rniobuf(struct niobuf_remote *nb)
-{
- CERROR("niobuf_remote: offset="LPD64", len=%d, flags=%x, xid=%d\n",
- nb->offset, nb->len, nb->flags, nb->xid);
-
- return -EINVAL;
-}
-
-int dump_obdo(struct obdo *oa)
-{
- __u32 valid = oa->o_valid;
-
- CERROR("obdo: o_valid = %08x\n", valid);
- if (valid & OBD_MD_FLID)
- CERROR("obdo: o_id = "LPD64"\n", oa->o_id);
- if (valid & OBD_MD_FLATIME)
- CERROR("obdo: o_atime = "LPD64"\n", oa->o_atime);
- if (valid & OBD_MD_FLMTIME)
- CERROR("obdo: o_mtime = "LPD64"\n", oa->o_mtime);
- if (valid & OBD_MD_FLCTIME)
- CERROR("obdo: o_ctime = "LPD64"\n", oa->o_ctime);
- if (valid & OBD_MD_FLSIZE)
- CERROR("obdo: o_size = "LPD64"\n", oa->o_size);
- if (valid & OBD_MD_FLBLOCKS) /* allocation of space */
- CERROR("obdo: o_blocks = "LPD64"\n", oa->o_blocks);
- if (valid & OBD_MD_FLBLKSZ)
- CERROR("obdo: o_blksize = %d\n", oa->o_blksize);
- if (valid & (OBD_MD_FLTYPE | OBD_MD_FLMODE))
- CERROR("obdo: o_mode = %o\n",
- oa->o_mode & ((valid & OBD_MD_FLTYPE ? S_IFMT : 0) |
- (valid & OBD_MD_FLMODE ? ~S_IFMT : 0)));
- if (valid & OBD_MD_FLUID)
- CERROR("obdo: o_uid = %d\n", oa->o_uid);
- if (valid & OBD_MD_FLGID)
- CERROR("obdo: o_gid = %d\n", oa->o_gid);
- if (valid & OBD_MD_FLFLAGS)
- CERROR("obdo: o_flags = %x\n", oa->o_flags);
- if (valid & OBD_MD_FLNLINK)
- CERROR("obdo: o_nlink = %d\n", oa->o_nlink);
- if (valid & OBD_MD_FLGENER)
- CERROR("obdo: o_generation = %d\n", oa->o_generation);
-
- return -EINVAL;
-}
-
-/* XXX assumes only a single page in request */
-/*
-int dump_req(struct ptlrpc_request *req)
-{
- struct ost_body *body = lustre_msg_buf(req->rq_reqmsg, 0);
- struct obd_ioobj *ioo = lustre_msg_buf(req->rq_reqmsg, 1);
- //struct niobuf *nb = lustre_msg_buf(req->rq_reqmsg, 2);
-
- dump_obdo(&body->oa);
- //dump_niobuf(nb);
- dump_ioo(ioo);
-
- return -EINVAL;
-}
-*/
-
-#define LPDS sizeof(__u64)
-int page_debug_setup(void *addr, int len, __u64 off, __u64 id)
-{
- LASSERT(addr);
-
- off = HTON__u64(off);
- id = HTON__u64(id);
- memcpy(addr, (char *)&off, LPDS);
- memcpy(addr + LPDS, (char *)&id, LPDS);
-
- addr += len - LPDS - LPDS;
- memcpy(addr, (char *)&off, LPDS);
- memcpy(addr + LPDS, (char *)&id, LPDS);
-
- return 0;
-}
-
-int page_debug_check(char *who, void *addr, int end, __u64 off, __u64 id)
-{
- __u64 ne_off;
- int err = 0;
-
- LASSERT(addr);
-
- ne_off = HTON__u64(off);
- id = HTON__u64(id);
- if (memcmp(addr, (char *)&ne_off, LPDS)) {
- CERROR("%s: id "LPU64" offset "LPU64" off: "LPX64" != "LPX64"\n",
- who, id, off, *(__u64 *)addr, ne_off);
- err = -EINVAL;
- }
- if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
- CERROR("%s: id "LPU64" offset "LPU64" id: "LPX64" != "LPX64"\n",
- who, id, off, *(__u64 *)(addr + LPDS), id);
- err = -EINVAL;
- }
-
- addr += end - LPDS - LPDS;
- if (memcmp(addr, (char *)&ne_off, LPDS)) {
- CERROR("%s: id "LPU64" offset "LPU64" end off: "LPX64" != "LPX64"\n",
- who, id, off, *(__u64 *)addr, ne_off);
- err = -EINVAL;
- }
- if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
- CERROR("%s: id "LPU64" offset "LPU64" end id: "LPX64" != "LPX64"\n",
- who, id, off, *(__u64 *)(addr + LPDS), id);
- err = -EINVAL;
- }
-
- return err;
-}
-#undef LPDS
-
-EXPORT_SYMBOL(dump_lniobuf);
-EXPORT_SYMBOL(dump_rniobuf);
-EXPORT_SYMBOL(dump_ioo);
-//EXPORT_SYMBOL(dump_req);
-EXPORT_SYMBOL(dump_obdo);
-EXPORT_SYMBOL(page_debug_setup);
-EXPORT_SYMBOL(page_debug_check);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2001, 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * These are the only exported functions, they provide some generic
- * infrastructure for managing object devices
- */
-
-#define DEBUG_SUBSYSTEM S_CLASS
-#include <linux/kmod.h> /* for request_module() */
-#include <linux/module.h>
-#include <linux/obd_class.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <linux/lprocfs_status.h>
-
-extern struct list_head obd_types;
-kmem_cache_t *obdo_cachep = NULL;
-kmem_cache_t *import_cachep = NULL;
-kmem_cache_t *export_cachep = NULL;
-
-int (*ptlrpc_put_connection_superhack)(struct ptlrpc_connection *c);
-
-/*
- * support functions: we could use inter-module communication, but this
- * is more portable to other OS's
- */
-static struct obd_type *class_search_type(char *nm)
-{
- struct list_head *tmp;
- struct obd_type *type;
- CDEBUG(D_INFO, "SEARCH %s\n", nm);
-
- tmp = &obd_types;
- list_for_each(tmp, &obd_types) {
- type = list_entry(tmp, struct obd_type, typ_chain);
- CDEBUG(D_INFO, "TYP %s\n", type->typ_name);
- if (strlen(type->typ_name) == strlen(nm) &&
- strcmp(type->typ_name, nm) == 0 ) {
- return type;
- }
- }
- return NULL;
-}
-
-struct obd_type *class_nm_to_type(char *nm)
-{
- struct obd_type *type = class_search_type(nm);
-
-#ifdef CONFIG_KMOD
- if ( !type ) {
- if ( !request_module(nm) ) {
- CDEBUG(D_INFO, "Loaded module '%s'\n", nm);
- type = class_search_type(nm);
- } else {
- CDEBUG(D_INFO, "Can't load module '%s'\n", nm);
- }
- }
-#endif
- return type;
-}
-
-int class_register_type(struct obd_ops *ops, struct lprocfs_vars *vars,
- char *nm)
-{
- struct obd_type *type;
- int rc;
-
- ENTRY;
-
- if (class_search_type(nm)) {
- CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
- RETURN(-EEXIST);
- }
-
- OBD_ALLOC(type, sizeof(*type));
- OBD_ALLOC(type->typ_ops, sizeof(*type->typ_ops));
- OBD_ALLOC(type->typ_name, strlen(nm) + 1);
- if (!type)
- RETURN(-ENOMEM);
- INIT_LIST_HEAD(&type->typ_chain);
- CDEBUG(D_INFO, "MOD_INC_USE for register_type: count = %d\n",
- atomic_read(&(THIS_MODULE)->uc.usecount));
- MOD_INC_USE_COUNT;
- list_add(&type->typ_chain, &obd_types);
- memcpy(type->typ_ops, ops, sizeof(*type->typ_ops));
- strcpy(type->typ_name, nm);
- rc = lprocfs_reg_class(type, vars, type);
-
- RETURN(rc);
-}
-
-int class_unregister_type(char *nm)
-{
- struct obd_type *type = class_nm_to_type(nm);
-
- ENTRY;
-
- if (!type) {
- CERROR("unknown obd type\n");
- RETURN(-EINVAL);
- }
-
- if (type->typ_refcnt) {
- CERROR("type %s has refcount (%d)\n", nm, type->typ_refcnt);
- /* This is a bad situation, let's make the best of it */
- /* Remove ops, but leave the name for debugging */
- OBD_FREE(type->typ_ops, sizeof(*type->typ_ops));
- RETURN(-EBUSY);
- }
- if(type->typ_procroot)
- lprocfs_dereg_class(type);
-
- list_del(&type->typ_chain);
- OBD_FREE(type->typ_name, strlen(nm) + 1);
- if (type->typ_ops != NULL)
- OBD_FREE(type->typ_ops, sizeof(*type->typ_ops));
- OBD_FREE(type, sizeof(*type));
- CDEBUG(D_INFO, "MOD_DEC_USE for register_type: count = %d\n",
- atomic_read(&(THIS_MODULE)->uc.usecount) - 1);
- MOD_DEC_USE_COUNT;
- RETURN(0);
-} /* class_unregister_type */
-
-int class_name2dev(char *name)
-{
- int res = -1;
- int i;
-
- if (!name)
- return -1;
-
- for (i=0; i < MAX_OBD_DEVICES; i++) {
- struct obd_device *obd = &obd_dev[i];
- if (obd->obd_name && strcmp(name, obd->obd_name) == 0) {
- res = i;
- return res;
- }
- }
-
- return res;
-}
-
-int class_uuid2dev(char *uuid)
-{
- int res = -1;
- int i;
-
- for (i=0; i < MAX_OBD_DEVICES; i++) {
- struct obd_device *obd = &obd_dev[i];
- if (strncmp(uuid, obd->obd_uuid, sizeof(obd->obd_uuid)) == 0) {
- res = i;
- return res;
- }
- }
-
- return res;
-}
-
-
-struct obd_device *class_uuid2obd(char *uuid)
-{
- int i;
-
- for (i=0; i < MAX_OBD_DEVICES; i++) {
- struct obd_device *obd = &obd_dev[i];
- if (strncmp(uuid, obd->obd_uuid, sizeof(obd->obd_uuid)) == 0)
- return obd;
- }
-
- return NULL;
-}
-
-void obd_cleanup_caches(void)
-{
- int rc;
- ENTRY;
- if (obdo_cachep) {
- rc = kmem_cache_destroy(obdo_cachep);
- if (rc)
- CERROR("Cannot destory ll_obdo_cache\n");
- obdo_cachep = NULL;
- }
- if (import_cachep) {
- rc = kmem_cache_destroy(import_cachep);
- if (rc)
- CERROR("Cannot destory ll_import_cache\n");
- import_cachep = NULL;
- }
- if (export_cachep) {
- rc = kmem_cache_destroy(export_cachep);
- if (rc)
- CERROR("Cannot destory ll_export_cache\n");
- export_cachep = NULL;
- }
- EXIT;
-}
-
-int obd_init_caches(void)
-{
- ENTRY;
- LASSERT(obdo_cachep == NULL);
- obdo_cachep = kmem_cache_create("ll_obdo_cache", sizeof(struct obdo),
- 0, 0, NULL, NULL);
- if (!obdo_cachep)
- GOTO(out, -ENOMEM);
-
- LASSERT(export_cachep == NULL);
- export_cachep = kmem_cache_create("ll_export_cache",
- sizeof(struct obd_export),
- 0, 0, NULL, NULL);
- if (!export_cachep)
- GOTO(out, -ENOMEM);
-
- LASSERT(import_cachep == NULL);
- import_cachep = kmem_cache_create("ll_import_cache",
- sizeof(struct obd_import),
- 0, 0, NULL, NULL);
- if (!import_cachep)
- GOTO(out, -ENOMEM);
-
- RETURN(0);
- out:
- obd_cleanup_caches();
- RETURN(-ENOMEM);
-
-}
-
-/* map connection to client */
-struct obd_export *class_conn2export(struct lustre_handle *conn)
-{
- struct obd_export *export;
- ENTRY;
-
- if (!conn) {
- CDEBUG(D_CACHE, "looking for null handle\n");
- RETURN(NULL);
- }
-
- if (conn->addr == -1) { /* this means assign a new connection */
- CDEBUG(D_CACHE, "want a new connection\n");
- RETURN(NULL);
- }
-
- if (!conn->addr) {
- CDEBUG(D_CACHE, "looking for null addr\n");
- fixme();
- RETURN(NULL);
- }
-
- CDEBUG(D_IOCTL, "looking for export addr "LPX64" cookie "LPX64"\n",
- conn->addr, conn->cookie);
- export = (struct obd_export *) (unsigned long)conn->addr;
- if (!kmem_cache_validate(export_cachep, (void *)export))
- RETURN(NULL);
-
- if (export->exp_cookie != conn->cookie)
- RETURN(NULL);
- RETURN(export);
-} /* class_conn2export */
-
-struct obd_device *class_conn2obd(struct lustre_handle *conn)
-{
- struct obd_export *export;
- export = class_conn2export(conn);
- if (export)
- return export->exp_obd;
- fixme();
- return NULL;
-}
-
-struct obd_import *class_conn2cliimp(struct lustre_handle *conn)
-{
- return &class_conn2obd(conn)->u.cli.cl_import;
-}
-
-struct obd_import *class_conn2ldlmimp(struct lustre_handle *conn)
-{
- return &class_conn2export(conn)->exp_ldlm_data.led_import;
-}
-
-struct obd_export *class_new_export(struct obd_device *obddev)
-{
- struct obd_export * export;
-
- export = kmem_cache_alloc(export_cachep, GFP_KERNEL);
- if (!export) {
- CERROR("no memory! (minor %d)\n", obddev->obd_minor);
- return NULL;
- }
-
- memset(export, 0, sizeof(*export));
- get_random_bytes(&export->exp_cookie, sizeof(export->exp_cookie));
- export->exp_obd = obddev;
- /* XXX this should be in LDLM init */
- INIT_LIST_HEAD(&export->exp_ldlm_data.led_held_locks);
- INIT_LIST_HEAD(&export->exp_conn_chain);
- spin_lock(&obddev->obd_dev_lock);
- list_add(&export->exp_obd_chain, &export->exp_obd->obd_exports);
- spin_unlock(&obddev->obd_dev_lock);
- return export;
-}
-
-void class_destroy_export(struct obd_export *exp)
-{
- ENTRY;
-
- LASSERT(exp->exp_cookie != DEAD_HANDLE_MAGIC);
-
- spin_lock(&exp->exp_obd->obd_dev_lock);
- list_del(&exp->exp_obd_chain);
- spin_unlock(&exp->exp_obd->obd_dev_lock);
-
- /* XXXshaver no connection here... */
- if (exp->exp_connection)
- spin_lock(&exp->exp_connection->c_lock);
- list_del(&exp->exp_conn_chain);
- if (exp->exp_connection) {
- spin_unlock(&exp->exp_connection->c_lock);
- ptlrpc_put_connection_superhack(exp->exp_connection);
- }
-
- exp->exp_cookie = DEAD_HANDLE_MAGIC;
- kmem_cache_free(export_cachep, exp);
-
- EXIT;
-}
-
-/* a connection defines an export context in which preallocation can
- be managed. */
-int class_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid)
-{
- struct obd_export * export;
- if (conn == NULL) {
- LBUG();
- return -EINVAL;
- }
-
- if (obd == NULL) {
- LBUG();
- return -EINVAL;
- }
-
- export = class_new_export(obd);
- if (!export)
- return -ENOMEM;
-
- conn->addr = (__u64) (unsigned long)export;
- conn->cookie = export->exp_cookie;
-
- CDEBUG(D_IOCTL, "connect: addr %Lx cookie %Lx\n",
- (long long)conn->addr, (long long)conn->cookie);
- return 0;
-}
-
-int class_disconnect(struct lustre_handle *conn)
-{
- struct obd_export *export;
- ENTRY;
-
- if (!(export = class_conn2export(conn))) {
- fixme();
- CDEBUG(D_IOCTL, "disconnect: attempting to free "
- "nonexistent client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- CDEBUG(D_IOCTL, "disconnect: addr %Lx cookie %Lx\n",
- (long long)conn->addr, (long long)conn->cookie);
-
- class_destroy_export(export);
-
- RETURN(0);
-}
-
-void class_disconnect_all(struct obd_device *obddev)
-{
- int again = 1;
-
- while (again) {
- spin_lock(&obddev->obd_dev_lock);
- if (!list_empty(&obddev->obd_exports)) {
- struct obd_export *export;
- struct lustre_handle conn;
- int rc;
-
- export = list_entry(obddev->obd_exports.next,
- struct obd_export,
- exp_obd_chain);
- conn.addr = (__u64)(unsigned long)export;
- conn.cookie = export->exp_cookie;
- spin_unlock(&obddev->obd_dev_lock);
- CERROR("force disconnecting %s:%s export %p\n",
- export->exp_obd->obd_type->typ_name,
- export->exp_connection->c_remote_uuid, export);
- rc = obd_disconnect(&conn);
- if (rc < 0) {
- /* AED: not so sure about this... We can't
- * loop here forever, yet we shouldn't leak
- * exports on a struct we will soon destroy.
- */
- CERROR("destroy export %p with err: rc = %d\n",
- export, rc);
- class_destroy_export(export);
- }
- } else {
- spin_unlock(&obddev->obd_dev_lock);
- again = 0;
- }
- }
-}
-
-#if 0
-
-/* FIXME: Data is a space- or comma-separated list of device IDs. This will
- * have to change. */
-int class_multi_setup(struct obd_device *obddev, uint32_t len, void *data)
-{
- int count, rc;
- char *p;
- ENTRY;
-
- for (p = data, count = 0; p < (char *)data + len; count++) {
- char *end;
- int tmp = simple_strtoul(p, &end, 0);
-
- if (p == end) {
- CERROR("invalid device ID starting at: %s\n", p);
- GOTO(err_disconnect, rc = -EINVAL);
- }
-
- if (tmp < 0 || tmp >= MAX_OBD_DEVICES) {
- CERROR("Trying to sub dev %d - dev no too large\n",
- tmp);
- GOTO(err_disconnect, rc = -EINVAL);
- }
-
- rc = obd_connect(&obddev->obd_multi_conn[count], &obd_dev[tmp]);
- if (rc) {
- CERROR("cannot connect to device %d: rc = %d\n", tmp,
- rc);
- GOTO(err_disconnect, rc);
- }
-
- CDEBUG(D_INFO, "target OBD %d is of type %s\n", count,
- obd_dev[tmp].obd_type->typ_name);
-
- p = end + 1;
- }
-
- obddev->obd_multi_count = count;
-
- RETURN(0);
-
- err_disconnect:
- for (count--; count >= 0; count--)
- obd_disconnect(&obddev->obd_multi_conn[count]);
- return rc;
-}
-
-/*
- * remove all connections to this device
- * close all connections to lower devices
- * needed for forced unloads of OBD client drivers
- */
-int class_multi_cleanup(struct obd_device *obddev)
-{
- int i;
-
- for (i = 0; i < obddev->obd_multi_count; i++) {
- int rc;
- struct obd_device *obd =
- class_conn2obd(&obddev->obd_multi_conn[i]);
-
- if (!obd) {
- CERROR("no such device [i %d]\n", i);
- RETURN(-EINVAL);
- }
-
- rc = obd_disconnect(&obddev->obd_multi_conn[i]);
- if (rc)
- CERROR("disconnect failure %d\n", obd->obd_minor);
- }
- return 0;
-}
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Hariharan Thantry thantry@users.sourceforge.net
- */
-#define EXPORT_SYMTAB
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-
-#define DEBUG_SUBSYSTEM S_CLASS
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-#ifdef LPROC_SNMP
-
-#define DEFAULT_MODE 0444
-/*
- * Tokenizer array. Change this array to include special
- * characters for string tokenizing
- */
-const char tok[] = {'/', '\0'};
-
-/*
- * Externs
- */
-extern struct proc_dir_entry proc_root; /* Defined in proc/root.c */
-
-/*
- * Globals
- */
-struct proc_dir_entry *proc_lustre_root;
-struct proc_dir_entry *proc_lustre_dev_root;
-struct proc_dir_entry *proc_lustre_fs_root;
-
-struct proc_dir_entry* lprocfs_mkdir(const char* dname,
- struct proc_dir_entry *parent)
-{
- struct proc_dir_entry *child_dir_entry;
- child_dir_entry = proc_mkdir(dname, parent);
- if (!child_dir_entry)
- CERROR("lustre: failed to create /proc entry %s\n", dname);
- return child_dir_entry;
-}
-
-struct proc_dir_entry* lprocfs_srch(struct proc_dir_entry* head,
- const char* name)
-{
- struct proc_dir_entry* temp;
- if (!head)
- return NULL;
- temp = head->subdir;
- while (temp != NULL) {
- if (!strcmp(temp->name, name))
- return temp;
- temp = temp->next;
- }
- return NULL;
-}
-
-void lprocfs_remove_all(struct proc_dir_entry* root)
-{
- struct proc_dir_entry *temp = root;
- struct proc_dir_entry *rm_entry;
- struct proc_dir_entry *parent = root->parent;
-
- while (1) {
- while (temp->subdir)
- temp = temp->subdir;
-
- rm_entry = temp;
- temp = temp->parent;
- remove_proc_entry(rm_entry->name, rm_entry->parent);
- if (temp == parent) break;
- }
-}
-
-#define MAX_STRING_SIZE 100
-struct proc_dir_entry* lprocfs_new_dir(struct proc_dir_entry* root,
- const char* string, const char* tok)
-{
- struct proc_dir_entry* new_root;
- struct proc_dir_entry* temp_entry;
- char temp_string[MAX_STRING_SIZE+1];
- char* my_str;
- char* mover_str;
-
- strncpy(temp_string, string, MAX_STRING_SIZE);
- temp_string[MAX_STRING_SIZE] = '\0';
-
- new_root = root;
- mover_str = temp_string;
- while ((my_str = strsep(&mover_str, tok))) {
- if(!*my_str)
- continue;
- CDEBUG(D_OTHER, "SEARCH= %s\t, ROOT=%s\n", my_str,
- new_root->name);
- temp_entry = lprocfs_srch(new_root, my_str);
- if (temp_entry == NULL) {
- CDEBUG(D_OTHER, "Adding: %s\n", my_str);
- temp_entry = lprocfs_mkdir(my_str, new_root);
- if (temp_entry == NULL) {
- CDEBUG(D_OTHER,
- "! Did not create new dir %s !!\n",
- my_str);
- return temp_entry;
- }
- }
- new_root = temp_entry;
- }
- return new_root;
-}
-
-int lprocfs_new_vars(struct proc_dir_entry* root,
- struct lprocfs_vars* list,
- const char* tok, void* data)
-{
- struct proc_dir_entry *temp_root;
- struct proc_dir_entry *new_leaf;
- struct proc_dir_entry *new_parent;
- char temp_string[MAX_STRING_SIZE+1];
-
- if (list == NULL)
- return 0;
-
- while (list->name) {
- temp_root = lprocfs_new_dir(root, list->name, tok);
- if (temp_root == NULL) {
- CDEBUG(D_OTHER, "!LProcFS: Mods: No root!");
- return -ENOMEM;
- }
-
- /* Convert the last element into a leaf-node */
- strncpy(temp_string, temp_root->name, MAX_STRING_SIZE);
- temp_string[MAX_STRING_SIZE] = '\0';
- new_parent = temp_root->parent;
- remove_proc_entry(temp_root->name, new_parent);
- new_leaf = create_proc_entry(temp_string, DEFAULT_MODE,
- new_parent);
- if (new_leaf == NULL) {
- CERROR("LprocFS: No memory to create /proc entry %s",
- temp_string);
- return -ENOMEM;
- }
- new_leaf->read_proc = list->read_fptr;
- new_leaf->write_proc = list->write_fptr;
- if (data)
- new_leaf->data=data;
- else
- new_leaf->data=list->data;
- list++;
- }
- return 0;
-
-}
-#undef MAX_STRING_SIZE
-/*
- * API implementations
- */
-int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *var,
- void *data)
-{
- return lprocfs_new_vars(root, var, tok, data);
-}
-
-int lprocfs_reg_obd(struct obd_device *device, struct lprocfs_vars *list,
- void *data)
-{
- struct proc_dir_entry* this_dev_root;
- int retval;
-
- if(lprocfs_srch(device->obd_type->typ_procroot, device->obd_name)){
- CDEBUG(D_OTHER, "Device with name [%s] exists!",
- device->obd_name);
- return 0;
- }
-
- /* Obtain this device root */
- this_dev_root = lprocfs_mkdir(device->obd_name,
- device->obd_type->typ_procroot);
-
- device->obd_proc_entry = this_dev_root;
- retval = lprocfs_add_vars(this_dev_root, list, data);
-
- return retval;
-}
-
-int lprocfs_dereg_obd(struct obd_device* device)
-{
- CDEBUG(D_OTHER, "LPROCFS removing device = %s\n", device->obd_name);
-
- if (device == NULL) {
- CDEBUG(D_OTHER, "! LProcfs: Null pointer !\n");
- return 0;
- }
- if (device->obd_proc_entry == NULL) {
- CDEBUG(D_OTHER, "! Proc entry non-existent !");
- return 0;
- }
- lprocfs_remove_all(device->obd_proc_entry);
- device->obd_proc_entry = NULL;
- if (device->counters)
- OBD_FREE(device->counters, device->cntr_mem_size);
-
- return 0;
-}
-
-struct proc_dir_entry* lprocfs_reg_mnt(char* mnt_name)
-{
- if(lprocfs_srch(proc_lustre_fs_root, mnt_name)){
- CDEBUG(D_OTHER, "Mount with same name exists!");
- return 0;
- }
- return lprocfs_mkdir(mnt_name, proc_lustre_fs_root);
-}
-
-int lprocfs_dereg_mnt(struct proc_dir_entry* root)
-{
- if(root == NULL){
- CDEBUG(D_OTHER, "Non-existent root!");
- return 0;
- }
- lprocfs_remove_all(root);
- return 0;
-}
-
-int lprocfs_reg_class(struct obd_type* type, struct lprocfs_vars* list,
- void* data)
-{
-
- struct proc_dir_entry* root;
- int retval;
- root = lprocfs_mkdir(type->typ_name, proc_lustre_dev_root);
- lprocfs_add_vars(root, list, data);
- type->typ_procroot = root;
- retval = lprocfs_add_vars(root, list, data);
- return retval;
-}
-
-int lprocfs_dereg_class(struct obd_type* class)
-{
- if(class == NULL){
- CDEBUG(D_OTHER, "Non-existent class",
- class->typ_name);
- return 0;
- }
- lprocfs_remove_all(class->typ_procroot);
- class->typ_procroot = NULL;
- CDEBUG(D_OTHER, "LPROCFS removed = %s\n", class->typ_name);
- return 0;
-
-}
-int lprocfs_reg_main()
-{
- proc_lustre_root = lprocfs_mkdir("lustre", &proc_root);
- if (proc_lustre_root == NULL) {
- CERROR(" !! Cannot create /proc/lustre !! \n");
- return -EINVAL;
- }
-
- proc_lustre_dev_root = lprocfs_mkdir("devices", proc_lustre_root);
- if (proc_lustre_dev_root == NULL) {
- CERROR(" !! Cannot create /proc/lustre/devices !! \n");
- return -EINVAL;
- }
- proc_lustre_fs_root = lprocfs_mkdir("mnt_pnt", proc_lustre_root);
-
- if (proc_lustre_fs_root == NULL) {
- CERROR(" !! Cannot create /proc/lustre/mnt_pnt !! \n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-int lprocfs_dereg_main()
-{
- lprocfs_remove_all(proc_lustre_root);
- proc_lustre_root = NULL;
- proc_lustre_dev_root = NULL;
- proc_lustre_fs_root = NULL;
- return 0;
-}
-
-
-/*
- * Needs to go...
- */
-int lprocfs_ll_rd(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- __u64 *temp = (__u64 *)data;
- int len;
- len = snprintf(page, count, LPU64"\n", *temp);
- return len;
-}
-
-#endif /* LPROC_SNMP */
-
-EXPORT_SYMBOL(lprocfs_reg_obd);
-EXPORT_SYMBOL(lprocfs_dereg_obd);
-EXPORT_SYMBOL(lprocfs_reg_main);
-EXPORT_SYMBOL(lprocfs_dereg_main);
-EXPORT_SYMBOL(lprocfs_reg_mnt);
-EXPORT_SYMBOL(lprocfs_dereg_mnt);
-EXPORT_SYMBOL(lprocfs_add_vars);
-EXPORT_SYMBOL(lprocfs_reg_class);
-EXPORT_SYMBOL(lprocfs_dereg_class);
-EXPORT_SYMBOL(lprocfs_ll_rd);
-
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/module.h>
-#include <linux/autoconf.h>
-#include <linux/sysctl.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/sysctl.h>
-#include <linux/swapctl.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/ctype.h>
-#include <asm/bitops.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/utsname.h>
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/obd_support.h>
-
-struct ctl_table_header *obd_table_header = NULL;
-
-static int vars[2];
-static int index = 0;
-
-static int obd_sctl_vars( ctl_table * table, int write, struct file *
- filp, void * buffer, size_t * lenp );
-static int obd_sctl_reset( ctl_table * table, int write, struct file
- * filp, void * buffer, size_t * lenp );
-
-#define OBD_SYSCTL 300
-
-#define OBD_FAIL_LOC 1 /* control test failures instrumentation */
-#define OBD_ENTRY 2 /* control enter/leave pattern */
-#define OBD_VARS 3
-#define OBD_INDEX 4
-#define OBD_RESET 5
-#define OBD_TIMEOUT 6 /* RPC timeout before recovery/intr */
-/* XXX move to /proc/sys/lustre/recovery? */
-#define OBD_UPCALL 7 /* path to recovery upcall */
-
-#define OBD_VARS_SLOT 2
-
-static ctl_table obd_table[] = {
- {OBD_FAIL_LOC, "fail_loc", &obd_fail_loc, sizeof(int), 0644, NULL, &proc_dointvec},
- {OBD_VARS, "vars", &vars[0], sizeof(int), 0644, NULL, &proc_dointvec},
- {OBD_INDEX, "index", &index, sizeof(int), 0644, NULL, &obd_sctl_vars},
- {OBD_RESET, "reset", NULL, 0, 0644, NULL, &obd_sctl_reset},
- {OBD_TIMEOUT, "timeout", &obd_timeout, sizeof(int), 0644, NULL, &proc_dointvec},
- /* XXX need to lock so we avoid update races with the recovery upcall! */
- {OBD_UPCALL, "recovery_upcall", obd_recovery_upcall, 128, 0644, NULL,
- &proc_dostring, &sysctl_string },
- { 0 }
-};
-
-static ctl_table parent_table[] = {
- {OBD_SYSCTL, "lustre", NULL, 0, 0555, obd_table},
- {0}
-};
-
-void obd_sysctl_init (void)
-{
-#ifdef CONFIG_SYSCTL
- if ( !obd_table_header )
- obd_table_header = register_sysctl_table(parent_table, 0);
-#endif
-}
-
-void obd_sysctl_clean (void)
-{
-#ifdef CONFIG_SYSCTL
- if ( obd_table_header )
- unregister_sysctl_table(obd_table_header);
- obd_table_header = NULL;
-#endif
-}
-
-int obd_sctl_reset (ctl_table * table, int write,
- struct file * filp, void * buffer,
- size_t * lenp)
-{
- if ( write ) {
- /* do something here */
- vars[0]=0;
- vars[1]=0;
- }
-
- *lenp = 0;
- return 0;
-}
-
-int obd_sctl_vars (ctl_table * table, int write,
- struct file * filp, void * buffer,
- size_t * lenp)
-{
- int rc;
-
- rc = proc_dointvec(table, write, filp, buffer, lenp);
-
- if ( rc )
- return rc;
-
- if ( index < 0 || index > 1 ) {
- CERROR("Illegal index %d!\n", index);
- index = 0;
- } else {
- obd_table[OBD_VARS_SLOT].data = &vars[index];
- }
-
- return rc;
-}
+++ /dev/null
-/*
- * Public include file for the UUID library
- *
- * Copyright (C) 1996, 1997, 1998 Theodore Ts'o.
- * Copyright (C) 2002 Cluster File System
- * - changed for use in lustre
- *
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU
- * Library General Public License.
- * %End-Header%
- */
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/smp_lock.h>
-
-struct uuid {
- __u32 time_low;
- __u16 time_mid;
- __u16 time_hi_and_version;
- __u16 clock_seq;
- __u8 node[6];
-};
-
-static void uuid_unpack(class_uuid_t in, struct uuid *uu)
-{
- __u8 *ptr = in;
- __u32 tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- tmp = (tmp << 8) | *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_low = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_mid = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->time_hi_and_version = tmp;
-
- tmp = *ptr++;
- tmp = (tmp << 8) | *ptr++;
- uu->clock_seq = tmp;
-
- memcpy(uu->node, ptr, 6);
-}
-
-#if 0
-static void uuid_pack(struct uuid *uu, class_uuid_t ptr)
-{
- __u32 tmp;
- unsigned char *out = ptr;
-
- tmp = uu->time_low;
- out[3] = (unsigned char) tmp;
- tmp >>= 8;
- out[2] = (unsigned char) tmp;
- tmp >>= 8;
- out[1] = (unsigned char) tmp;
- tmp >>= 8;
- out[0] = (unsigned char) tmp;
-
- tmp = uu->time_mid;
- out[5] = (unsigned char) tmp;
- tmp >>= 8;
- out[4] = (unsigned char) tmp;
-
- tmp = uu->time_hi_and_version;
- out[7] = (unsigned char) tmp;
- tmp >>= 8;
- out[6] = (unsigned char) tmp;
-
- tmp = uu->clock_seq;
- out[9] = (unsigned char) tmp;
- tmp >>= 8;
- out[8] = (unsigned char) tmp;
-
- memcpy(out+10, uu->node, 6);
-}
-
-int class_uuid_parse(obd_uuid_t in, class_uuid_t uu)
-{
- struct uuid uuid;
- int i;
- char *cp, buf[3];
-
- if (strlen(in) != 36)
- return -1;
- for (i=0, cp = in; i <= 36; i++,cp++) {
- if ((i == 8) || (i == 13) || (i == 18) ||
- (i == 23))
- if (*cp == '-')
- continue;
- if (i== 36)
- if (*cp == 0)
- continue;
- if (!isxdigit(*cp))
- return -1;
- }
- uuid.time_low = simple_strtoul(in, NULL, 16);
- uuid.time_mid = simple_strtoul(in+9, NULL, 16);
- uuid.time_hi_and_version = simple_strtoul(in+14, NULL, 16);
- uuid.clock_seq = simple_strtoul(in+19, NULL, 16);
- cp = in+24;
- buf[2] = 0;
- for (i=0; i < 6; i++) {
- buf[0] = *cp++;
- buf[1] = *cp++;
- uuid.node[i] = simple_strtoul(buf, NULL, 16);
- }
-
- uuid_pack(&uuid, uu);
- return 0;
-}
-#endif
-
-void class_uuid_unparse(class_uuid_t uu, obd_uuid_t out)
-{
- struct uuid uuid;
-
- uuid_unpack(uu, &uuid);
- sprintf(out,
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
- uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
- uuid.node[0], uuid.node[1], uuid.node[2],
- uuid.node[3], uuid.node[4], uuid.node[5]);
-}
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=
-MODULE = obdecho
-modulefs_DATA = obdecho.o
-EXTRA_PROGRAMS = obdecho
-
-LINX=
-obdecho_SOURCES = echo.c echo_client.c lproc_echo.c $(LINX)
-
-include $(top_srcdir)/Rules
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2001, 2002 Cluster File Systems, Inc.
- * Author: Peter Braam <braam@clusterfs.com>
- * Author: Andreas Dilger <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define OBDECHO_VERSION "1.0"
-
-#define EXPORT_SYMTAB
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/ext2_fs.h>
-#include <linux/quotaops.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-#include <asm/unistd.h>
-
-#define DEBUG_SUBSYSTEM S_ECHO
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/obd_echo.h>
-#include <linux/lustre_debug.h>
-#include <linux/lustre_dlm.h>
-#include <linux/lprocfs_status.h>
-
-static atomic_t echo_page_rws;
-static atomic_t echo_getattrs;
-
-#define ECHO_PROC_STAT "sys/obdecho"
-#define ECHO_INIT_OBJID 0x1000000000000000ULL
-
-extern struct lprocfs_vars status_var_nm_1[];
-extern struct lprocfs_vars status_class_var[];
-
-int echo_proc_read(char *page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- long long attrs = atomic_read(&echo_getattrs);
- long long pages = atomic_read(&echo_page_rws);
- int len;
-
- *eof = 1;
- if (off != 0)
- return (0);
-
- len = sprintf(page, "%Ld %Ld\n", attrs, pages);
-
- *start = page;
- return (len);
-}
-
-int echo_proc_write(struct file *file, const char *ubuffer,
- unsigned long count, void *data)
-{
- /* Ignore what we've been asked to write, and just zero the counters */
- atomic_set (&echo_page_rws, 0);
- atomic_set (&echo_getattrs, 0);
-
- return (count);
-}
-
-void echo_proc_init(void)
-{
- struct proc_dir_entry *entry;
-
- entry = create_proc_entry(ECHO_PROC_STAT, S_IFREG|S_IRUGO|S_IWUSR,NULL);
-
- if (entry == NULL) {
- CERROR("couldn't create proc entry %s\n", ECHO_PROC_STAT);
- return;
- }
-
- entry->data = NULL;
- entry->read_proc = echo_proc_read;
- entry->write_proc = echo_proc_write;
-}
-
-void echo_proc_fini(void)
-{
- remove_proc_entry(ECHO_PROC_STAT, 0);
-}
-
-static int echo_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- int rc;
-
- MOD_INC_USE_COUNT;
- rc = class_connect(conn, obd, cluuid);
-
- if (rc)
- MOD_DEC_USE_COUNT;
-
- return rc;
-}
-
-static int echo_disconnect(struct lustre_handle *conn)
-{
- int rc;
-
- rc = class_disconnect(conn);
- if (!rc)
- MOD_DEC_USE_COUNT;
-
- return rc;
-}
-
-static __u64 echo_next_id(struct obd_device *obddev)
-{
- obd_id id;
-
- spin_lock(&obddev->u.echo.eo_lock);
- id = ++obddev->u.echo.eo_lastino;
- spin_unlock(&obddev->u.echo.eo_lock);
-
- return id;
-}
-
-int echo_create(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md **ea)
-{
- struct obd_device *obd = class_conn2obd(conn);
-
- if (!obd) {
- CERROR("invalid client %Lx\n", conn->addr);
- return -EINVAL;
- }
-
- if (!(oa->o_mode && S_IFMT)) {
- CERROR("filter obd: no type!\n");
- return -ENOENT;
- }
-
- if (!(oa->o_valid & OBD_MD_FLTYPE)) {
- CERROR("invalid o_valid %08x\n", oa->o_valid);
- return -EINVAL;
- }
-
- oa->o_id = echo_next_id(obd);
- oa->o_valid = OBD_MD_FLID;
- atomic_inc(&obd->u.echo.eo_create);
-
- return 0;
-}
-
-int echo_destroy(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea)
-{
- struct obd_device *obd = class_conn2obd(conn);
-
- if (!obd) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- if (!(oa->o_valid & OBD_MD_FLID)) {
- CERROR("obdo missing FLID valid flag: %08x\n", oa->o_valid);
- RETURN(-EINVAL);
- }
-
- if (oa->o_id > obd->u.echo.eo_lastino || oa->o_id < ECHO_INIT_OBJID) {
- CERROR("bad destroy objid: "LPX64"\n", oa->o_id);
- RETURN(-EINVAL);
- }
-
- atomic_inc(&obd->u.echo.eo_destroy);
-
- return 0;
-}
-
-static int echo_open(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- return 0;
-}
-
-static int echo_close(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- return 0;
-}
-
-static int echo_getattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- struct obd_device *obd = class_conn2obd(conn);
- obd_id id = oa->o_id;
-
- if (!obd) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- if (!(oa->o_valid & OBD_MD_FLID)) {
- CERROR("obdo missing FLID valid flag: %08x\n", oa->o_valid);
- RETURN(-EINVAL);
- }
-
- memcpy(oa, &obd->u.echo.oa, sizeof(*oa));
- oa->o_id = id;
- oa->o_valid |= OBD_MD_FLID;
-
- atomic_inc(&echo_getattrs);
-
- return 0;
-}
-
-static int echo_setattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- struct obd_device *obd = class_conn2obd(conn);
-
- if (!obd) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- if (!(oa->o_valid & OBD_MD_FLID)) {
- CERROR("obdo missing FLID valid flag: %08x\n", oa->o_valid);
- RETURN(-EINVAL);
- }
-
- memcpy(&obd->u.echo.oa, oa, sizeof(*oa));
-
- atomic_inc(&obd->u.echo.eo_setattr);
-
- return 0;
-}
-
-/* This allows us to verify that desc_private is passed unmolested */
-#define DESC_PRIV 0x10293847
-
-int echo_preprw(int cmd, struct lustre_handle *conn, int objcount,
- struct obd_ioobj *obj, int niocount, struct niobuf_remote *nb,
- struct niobuf_local *res, void **desc_private)
-{
- struct obd_device *obd;
- struct niobuf_local *r = res;
- int rc = 0;
- int i;
-
- ENTRY;
-
- obd = class_conn2obd(conn);
- if (!obd) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- memset(res, 0, sizeof(*res) * niocount);
-
- CDEBUG(D_PAGE, "%s %d obdos with %d IOs\n",
- cmd == OBD_BRW_READ ? "reading" : "writing", objcount, niocount);
-
- *desc_private = (void *)DESC_PRIV;
-
- obd_kmap_get(niocount, 1);
-
- for (i = 0; i < objcount; i++, obj++) {
- int gfp_mask = (obj->ioo_id & 1) ? GFP_HIGHUSER : GFP_KERNEL;
- int verify = obj->ioo_id != 0;
- int j;
-
- for (j = 0 ; j < obj->ioo_bufcnt ; j++, nb++, r++) {
- r->page = alloc_pages(gfp_mask, 0);
- if (!r->page) {
- CERROR("can't get page %d/%d for id "LPU64"\n",
- j, obj->ioo_bufcnt, obj->ioo_id);
- GOTO(preprw_cleanup, rc = -ENOMEM);
- }
- atomic_inc(&obd->u.echo.eo_prep);
-
- r->offset = nb->offset;
- r->addr = kmap(r->page);
- r->len = nb->len;
-
- CDEBUG(D_PAGE, "$$$$ get page %p, addr %p@"LPU64"\n",
- r->page, r->addr, r->offset);
-
- if (verify && cmd == OBD_BRW_READ)
- page_debug_setup(r->addr, r->len, r->offset,
- obj->ioo_id);
- else if (verify)
- page_debug_setup(r->addr, r->len,
- 0xecc0ecc0ecc0ecc0,
- 0xecc0ecc0ecc0ecc0);
- }
- }
- CDEBUG(D_PAGE, "%d pages allocated after prep\n",
- atomic_read(&obd->u.echo.eo_prep));
-
- RETURN(0);
-
-preprw_cleanup:
- /* It is possible that we would rather handle errors by allow
- * any already-set-up pages to complete, rather than tearing them
- * all down again. I believe that this is what the in-kernel
- * prep/commit operations do.
- */
- CERROR("cleaning up %ld pages (%d obdos)\n", (long)(r - res), objcount);
- while (r-- > res) {
- kunmap(r->page);
- __free_pages(r->page, 0);
- atomic_dec(&obd->u.echo.eo_prep);
- }
- obd_kmap_put(niocount);
- memset(res, 0, sizeof(*res) * niocount);
-
- return rc;
-}
-
-int echo_commitrw(int cmd, struct lustre_handle *conn, int objcount,
- struct obd_ioobj *obj, int niocount, struct niobuf_local *res,
- void *desc_private)
-{
- struct obd_device *obd;
- struct niobuf_local *r = res;
- int rc = 0;
- int i;
- ENTRY;
-
- obd = class_conn2obd(conn);
- if (!obd) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- if ((cmd & OBD_BRW_RWMASK) == OBD_BRW_READ) {
- CDEBUG(D_PAGE, "reading %d obdos with %d IOs\n",
- objcount, niocount);
- } else {
- CDEBUG(D_PAGE, "writing %d obdos with %d IOs\n",
- objcount, niocount);
- }
-
- if (niocount && !r) {
- CERROR("NULL res niobuf with niocount %d\n", niocount);
- RETURN(-EINVAL);
- }
-
- LASSERT(desc_private == (void *)DESC_PRIV);
-
- for (i = 0; i < objcount; i++, obj++) {
- int verify = obj->ioo_id != 0;
- int j;
-
- for (j = 0 ; j < obj->ioo_bufcnt ; j++, r++) {
- struct page *page = r->page;
- void *addr;
-
- if (!page || !(addr = page_address(page)) ||
- !kern_addr_valid(addr)) {
-
- CERROR("bad page objid "LPU64":%p, buf %d/%d\n",
- obj->ioo_id, page, j, obj->ioo_bufcnt);
- GOTO(commitrw_cleanup, rc = -EFAULT);
- }
-
- atomic_inc(&echo_page_rws);
-
- CDEBUG(D_PAGE, "$$$$ use page %p, addr %p@"LPU64"\n",
- r->page, addr, r->offset);
-
- if (verify)
- page_debug_check("echo", addr, r->len,
- r->offset, obj->ioo_id);
-
- kunmap(page);
- obd_kmap_put(1);
- __free_pages(page, 0);
- atomic_dec(&obd->u.echo.eo_prep);
- }
- }
- CDEBUG(D_PAGE, "%d pages remain after commit\n",
- atomic_read(&obd->u.echo.eo_prep));
- RETURN(0);
-
-commitrw_cleanup:
- CERROR("cleaning up %ld pages (%d obdos)\n",
- niocount - (long)(r - res) - 1, objcount);
- while (++r < res + niocount) {
- struct page *page = r->page;
-
- kunmap(page);
- obd_kmap_put(1);
- __free_pages(page, 0);
- atomic_dec(&obd->u.echo.eo_prep);
- }
- return rc;
-}
-
-static int echo_setup(struct obd_device *obddev, obd_count len, void *buf)
-{
- ENTRY;
-
- obddev->obd_namespace =
- ldlm_namespace_new("echo-tgt", LDLM_NAMESPACE_SERVER);
- if (obddev->obd_namespace == NULL) {
- LBUG();
- RETURN(-ENOMEM);
- }
- spin_lock_init(&obddev->u.echo.eo_lock);
- obddev->u.echo.eo_lastino = ECHO_INIT_OBJID;
-
- RETURN(0);
-}
-
-static int echo_cleanup(struct obd_device *obddev)
-{
- ENTRY;
-
- ldlm_namespace_free(obddev->obd_namespace);
- CERROR("%d prep/commitrw pages leaked\n",
- atomic_read(&obddev->u.echo.eo_prep));
-
- RETURN(0);
-}
-
-int echo_attach(struct obd_device *dev, obd_count len, void *data)
-{
- return lprocfs_reg_obd(dev, status_var_nm_1, dev);
-}
-
-int echo_detach(struct obd_device *dev)
-{
- return lprocfs_dereg_obd(dev);
-}
-
-static struct obd_ops echo_obd_ops = {
- o_attach: echo_attach,
- o_detach: echo_detach,
- o_connect: echo_connect,
- o_disconnect: echo_disconnect,
- o_create: echo_create,
- o_destroy: echo_destroy,
- o_open: echo_open,
- o_close: echo_close,
- o_getattr: echo_getattr,
- o_setattr: echo_setattr,
- o_preprw: echo_preprw,
- o_commitrw: echo_commitrw,
- o_setup: echo_setup,
- o_cleanup: echo_cleanup
-};
-
-extern int echo_client_init(void);
-extern void echo_client_cleanup(void);
-
-static int __init obdecho_init(void)
-{
- int rc;
-
- printk(KERN_INFO "Echo OBD driver " OBDECHO_VERSION
- " info@clusterfs.com\n");
-
- echo_proc_init();
- rc = class_register_type(&echo_obd_ops, status_class_var,
- OBD_ECHO_DEVICENAME);
- if (rc)
- RETURN(rc);
-
- rc = echo_client_init();
- if (rc)
- class_unregister_type(OBD_ECHO_DEVICENAME);
-
- RETURN(rc);
-}
-
-static void __exit obdecho_exit(void)
-{
- echo_proc_fini();
- echo_client_cleanup();
- class_unregister_type(OBD_ECHO_DEVICENAME);
-}
-
-MODULE_AUTHOR("Cluster Filesystems Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Testing Echo OBD driver " OBDECHO_VERSION);
-MODULE_LICENSE("GPL");
-
-module_init(obdecho_init);
-module_exit(obdecho_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (c) 2001, 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-
-#define DEBUG_SUBSYSTEM S_ECHO
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/obd_echo.h>
-#include <linux/lustre_debug.h>
-#include <linux/lprocfs_status.h>
-
-static int echo_iocontrol(unsigned int cmd, struct lustre_handle *obdconn, int len,
- void *karg, void *uarg)
-{
- struct obd_device *obd = class_conn2obd(obdconn);
- struct echo_client_obd *ec = &obd->u.echo_client;
- struct obd_ioctl_data *data = karg;
- int rw = OBD_BRW_READ, rc = 0;
- struct lov_stripe_md *lsm = NULL;
- ENTRY;
-
- if (obd == NULL) {
- CERROR("ioctl: No device\n");
- GOTO(out, rc = -EINVAL);
- }
-
- if (data->ioc_inllen1 == sizeof(*lsm)) {
- lsm = (struct lov_stripe_md *)data->ioc_inlbuf1;
- } else if (data->ioc_inllen1 != 0) {
- CERROR("nonzero ioc_inllen1 != sizeof(struct lov_stripe_md)\n");
- GOTO(out, rc = -EINVAL);
- }
-
- switch (cmd) {
- case OBD_IOC_CREATE: {
- struct lov_stripe_md *tmp_lsm = NULL;
- rc = obd_create(&ec->conn, &data->ioc_obdo1, &tmp_lsm);
- if (lsm)
- memcpy(lsm, tmp_lsm, sizeof(*tmp_lsm));
-
- GOTO(out, rc);
- }
-
- case OBD_IOC_GETATTR:
- rc = obd_getattr(&ec->conn, &data->ioc_obdo1, lsm);
- GOTO(out, rc);
-
- case OBD_IOC_SETATTR:
- rc = obd_setattr(&ec->conn, &data->ioc_obdo1, lsm);
- GOTO(out, rc);
-
- case OBD_IOC_DESTROY:
- rc = obd_destroy(&ec->conn, &data->ioc_obdo1, lsm);
- GOTO(out, rc);
-
- case OBD_IOC_OPEN:
- rc = obd_open(&ec->conn, &data->ioc_obdo1, lsm);
- GOTO(out, rc);
-
- case OBD_IOC_CLOSE:
- rc = obd_close(&ec->conn, &data->ioc_obdo1, lsm);
- GOTO(out, rc);
-
- case OBD_IOC_BRW_WRITE:
- rw = OBD_BRW_WRITE;
- case OBD_IOC_BRW_READ: {
- struct lov_stripe_md tmp_lsm;
- struct obd_brw_set *set;
- obd_count pages = 0;
- struct brw_page *pga, *pgp;
- __u64 off, id = data->ioc_obdo1.o_id;
- int gfp_mask = (id & 1) ? GFP_HIGHUSER : GFP_KERNEL;
- int j, verify = (id != 0);
-
- if (lsm && lsm->lsm_object_id != id) {
- CERROR("LSM object ID ("LPU64") != id ("LPU64")\n",
- lsm->lsm_object_id, id);
- GOTO(out, rc = -EINVAL);
- }
-
- if (!lsm) {
- memset(&tmp_lsm, 0, sizeof(tmp_lsm));
- lsm = &tmp_lsm;
- lsm->lsm_object_id = id;
- }
-
- if (data->ioc_count < 0) {
- CERROR("invalid buffer size: "LPD64"\n",
- data->ioc_count);
- GOTO(out, rc = -EINVAL);
- }
-
- set = obd_brw_set_new();
- if (set == NULL)
- GOTO(out, rc = -ENOMEM);
-
- pages = data->ioc_count / PAGE_SIZE;
- off = data->ioc_offset;
-
- CDEBUG(D_INODE, "BRW %s with %d pages @ "LPX64"\n",
- rw == OBD_BRW_READ ? "read" : "write", pages, off);
- OBD_ALLOC(pga, pages * sizeof(*pga));
- if (!pga) {
- CERROR("no memory for %d BRW per-page data\n", pages);
- GOTO(brw_free, rc = -ENOMEM);
- }
-
- for (j = 0, pgp = pga; j < pages; j++, off += PAGE_SIZE, pgp++){
- pgp->pg = alloc_pages(gfp_mask, 0);
- if (!pgp->pg) {
- CERROR("no memory for brw pages\n");
- GOTO(brw_cleanup, rc = -ENOMEM);
- }
- pgp->count = PAGE_SIZE;
- pgp->off = off;
- pgp->flag = 0;
-
- if (verify) {
- void *addr = kmap(pgp->pg);
-
- if (rw == OBD_BRW_WRITE)
- page_debug_setup(addr, pgp->count,
- pgp->off, id);
- else
- page_debug_setup(addr, pgp->count,
- 0xdeadbeef00c0ffee,
- 0xdeadbeef00c0ffee);
- kunmap(pgp->pg);
- }
- }
-
- set->brw_callback = ll_brw_sync_wait;
- rc = obd_brw(rw, &ec->conn, lsm, j, pga, set);
- if (rc)
- CERROR("test_brw: error from obd_brw: rc = %d\n", rc);
- else {
- rc = ll_brw_sync_wait(set, CB_PHASE_START);
- if (rc)
- CERROR("test_brw: error from callback: rc = "
- "%d\n", rc);
- }
- EXIT;
- brw_cleanup:
- for (j = 0, pgp = pga; j < pages; j++, pgp++) {
- if (pgp->pg == NULL)
- continue;
-
- if (verify && !rc) {
- void *addr = kmap(pgp->pg);
-
- rc = page_debug_check("test_brw", addr,
- PAGE_SIZE, pgp->off, id);
- kunmap(pgp->pg);
- }
- __free_pages(pgp->pg, 0);
- }
- brw_free:
- obd_brw_set_free(set);
- OBD_FREE(pga, pages * sizeof(*pga));
- GOTO(out, rc);
- }
- default:
- CERROR ("echo_ioctl(): unrecognised ioctl %#lx\n", cmd);
- GOTO (out, rc = -ENOTTY);
- }
-
- out:
- RETURN(rc);
-}
-
-static int echo_setup(struct obd_device *obddev, obd_count len, void *buf)
-{
- struct obd_ioctl_data* data = buf;
- struct echo_client_obd *ec = &obddev->u.echo_client;
- struct obd_device *tgt;
- int rc;
- ENTRY;
-
- if (data->ioc_inllen1 < 1) {
- CERROR("requires a TARGET OBD UUID\n");
- RETURN(-EINVAL);
- }
- if (data->ioc_inllen1 > 37) {
- CERROR("OBD UUID must be less than 38 characters\n");
- RETURN(-EINVAL);
- }
-
- MOD_INC_USE_COUNT;
- tgt = class_uuid2obd(data->ioc_inlbuf1);
- if (!tgt || !(tgt->obd_flags & OBD_ATTACHED) ||
- !(tgt->obd_flags & OBD_SET_UP)) {
- CERROR("device not attached or not set up (%d)\n",
- data->ioc_dev);
- GOTO(error_dec, rc = -EINVAL);
- }
-
- rc = obd_connect(&ec->conn, tgt, NULL, NULL, NULL);
- if (rc) {
- CERROR("fail to connect to device %d\n", data->ioc_dev);
- GOTO(error_dec, rc = -EINVAL);
- }
- RETURN(rc);
-error_dec:
- MOD_DEC_USE_COUNT;
- RETURN(rc);
-}
-
-static int echo_cleanup(struct obd_device * obddev)
-{
- struct echo_client_obd *ec = &obddev->u.echo_client;
- int rc;
- ENTRY;
-
- if (!list_empty(&obddev->obd_exports)) {
- CERROR("still has clients!\n");
- RETURN(-EBUSY);
- }
-
- rc = obd_disconnect(&ec->conn);
- if (rc) {
- CERROR("fail to disconnect device: %d\n", rc);
- RETURN(-EINVAL);
- }
-
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-static int echo_connect(struct lustre_handle *conn, struct obd_device *src,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- return class_connect(conn, src, cluuid);
-}
-
-static struct obd_ops echo_obd_ops = {
- o_setup: echo_setup,
- o_cleanup: echo_cleanup,
- o_iocontrol: echo_iocontrol,
- o_connect: echo_connect,
- o_disconnect: class_disconnect
-};
-
-int echo_client_init(void)
-{
- extern struct lprocfs_vars status_class_var[];
-
- return class_register_type(&echo_obd_ops, status_class_var,
- OBD_ECHO_CLIENT_DEVICENAME);
-}
-
-void echo_client_cleanup(void)
-{
- class_unregister_type(OBD_ECHO_CLIENT_DEVICENAME);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_ECHO
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-
-int rd_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct obd_device* dev = (struct obd_device*)data;
- len += snprintf(page, count, "%s\n", dev->obd_uuid);
- return len;
-
-}
-
-int rd_fstype(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct obd_device* dev = (struct obd_device*)data;
- len += snprintf(page, count, "%s\n", dev->u.echo.eo_fstype);
- return len;
-
-}
-
-
-struct lprocfs_vars status_var_nm_1[] = {
- {"status/uuid", rd_uuid, 0, 0},
- {"status/fstype", rd_fstype, 0, 0},
- {0}
-};
-
-int rd_numrefs(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_type* class = (struct obd_type*)data;
- int len = 0;
- len += snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-struct lprocfs_vars status_class_var[] = {
- {"status/num_refs", rd_numrefs, 0, 0},
- {0}
-};
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=
-MODULE = obdfilter
-modulefs_DATA = obdfilter.o
-EXTRA_PROGRAMS = obdfilter
-
-LINX=simple.c ll_pack.c
-ll_pack.c:
- test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c
-
-simple.c:
- test -e simple.c || ln -sf $(top_srcdir)/lib/simple.c
-
-FILTERC = filter.c lproc_obdfilter.c
-obdfilter_SOURCES = $(FILTERC) $(LINX)
-
-dist-hook:
- list='$(LINX)'; for f in $$list; do rm -f $(distdir)/$$f; done
-
-include $(top_srcdir)/Rules
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * linux/fs/obdfilter/filter.c
- *
- * Copyright (c) 2001, 2002 Cluster File Systems, Inc.
- * Author: Peter Braam <braam@clusterfs.com>
- * Author: Andreas Dilger <adilger@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_FILTER
-
-#include <linux/module.h>
-#include <linux/pagemap.h>
-#include <linux/fs.h>
-#include <linux/dcache.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_dlm.h>
-#include <linux/obd_filter.h>
-#include <linux/ext3_jbd.h>
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#include <linux/extN_jbd.h>
-#endif
-#include <linux/quotaops.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <linux/stringify.h>
-#include <linux/lprocfs_status.h>
-
-extern struct lprocfs_vars status_class_var[];
-extern struct lprocfs_vars status_var_nm_1[];
-
-static kmem_cache_t *filter_open_cache;
-static kmem_cache_t *filter_dentry_cache;
-
-#define FILTER_ROOTINO 2
-#define FILTER_ROOTINO_STR __stringify(FILTER_ROOTINO)
-
-#define S_SHIFT 12
-static char *obd_type_by_mode[S_IFMT >> S_SHIFT] = {
- [0] NULL,
- [S_IFREG >> S_SHIFT] "R",
- [S_IFDIR >> S_SHIFT] "D",
- [S_IFCHR >> S_SHIFT] "C",
- [S_IFBLK >> S_SHIFT] "B",
- [S_IFIFO >> S_SHIFT] "F",
- [S_IFSOCK >> S_SHIFT] "S",
- [S_IFLNK >> S_SHIFT] "L"
-};
-
-static inline const char *obd_mode_to_type(int mode)
-{
- return obd_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
-}
-
-/* write the pathname into the string */
-static int filter_id(char *buf, obd_id id, obd_mode mode)
-{
- return sprintf(buf, "O/%s/"LPU64, obd_mode_to_type(mode), id);
-}
-
-static inline void f_dput(struct dentry *dentry)
-{
- /* Can't go inside filter_ddelete because it can block */
- CDEBUG(D_INODE, "putting %s: %p, count = %d\n",
- dentry->d_name.name, dentry, atomic_read(&dentry->d_count) - 1);
- LASSERT(atomic_read(&dentry->d_count) > 0);
-
- dput(dentry);
-}
-
-/* Not racy w.r.t. others, because we are the only user of this dentry */
-static void filter_drelease(struct dentry *dentry)
-{
- if (dentry->d_fsdata)
- kmem_cache_free(filter_dentry_cache, dentry->d_fsdata);
-}
-
-struct dentry_operations filter_dops = {
- .d_release = filter_drelease,
-};
-
-/* setup the object store with correct subdirectories */
-static int filter_prep(struct obd_device *obd)
-{
- struct obd_run_ctxt saved;
- struct filter_obd *filter = &obd->u.filter;
- struct dentry *dentry;
- struct dentry *root;
- struct file *file;
- struct inode *inode;
- int rc = 0;
- __u64 lastobjid = 2;
- int mode = 0;
-
- push_ctxt(&saved, &filter->fo_ctxt, NULL);
- dentry = simple_mkdir(current->fs->pwd, "O", 0700);
- CDEBUG(D_INODE, "got/created O: %p\n", dentry);
- if (IS_ERR(dentry)) {
- rc = PTR_ERR(dentry);
- CERROR("cannot open/create O: rc = %d\n", rc);
- GOTO(out, rc);
- }
- filter->fo_dentry_O = dentry;
- dentry = simple_mkdir(current->fs->pwd, "P", 0700);
- CDEBUG(D_INODE, "got/created P: %p\n", dentry);
- if (IS_ERR(dentry)) {
- rc = PTR_ERR(dentry);
- CERROR("cannot open/create P: rc = %d\n", rc);
- GOTO(out_O, rc);
- }
- f_dput(dentry);
- dentry = simple_mkdir(current->fs->pwd, "D", 0700);
- CDEBUG(D_INODE, "got/created D: %p\n", dentry);
- if (IS_ERR(dentry)) {
- rc = PTR_ERR(dentry);
- CERROR("cannot open/create D: rc = %d\n", rc);
- GOTO(out_O, rc);
- }
-
- root = simple_mknod(dentry, FILTER_ROOTINO_STR, S_IFREG | 0755);
- f_dput(dentry);
- if (IS_ERR(root)) {
- rc = PTR_ERR(root);
- CERROR("OBD filter: cannot open/create root %d: rc = %d\n",
- FILTER_ROOTINO, rc);
- GOTO(out_O, rc);
- }
- f_dput(root);
-
- /*
- * Create directories and/or get dentries for each object type.
- * This saves us from having to do multiple lookups for each one.
- */
- for (mode = 0; mode < (S_IFMT >> S_SHIFT); mode++) {
- char *type = obd_type_by_mode[mode];
-
- if (!type) {
- filter->fo_dentry_O_mode[mode] = NULL;
- continue;
- }
- dentry = simple_mkdir(filter->fo_dentry_O, type, 0700);
- CDEBUG(D_INODE, "got/created O/%s: %p\n", type, dentry);
- if (IS_ERR(dentry)) {
- rc = PTR_ERR(dentry);
- CERROR("cannot create O/%s: rc = %d\n", type, rc);
- GOTO(out_O_mode, rc);
- }
- filter->fo_dentry_O_mode[mode] = dentry;
- }
-
- file = filp_open("D/status", O_RDWR | O_CREAT, 0700);
- if ( !file || IS_ERR(file) ) {
- rc = PTR_ERR(file);
- CERROR("OBD filter: cannot open/create status %s: rc = %d\n",
- "D/status", rc);
- GOTO(out_O_mode, rc);
- }
-
- /* steal operations */
- inode = file->f_dentry->d_inode;
- filter->fo_fop = file->f_op;
- filter->fo_iop = inode->i_op;
- filter->fo_aops = inode->i_mapping->a_ops;
-
- if (inode->i_size == 0) {
- __u64 disk_lastobjid = cpu_to_le64(lastobjid);
- ssize_t retval = file->f_op->write(file,(char *)&disk_lastobjid,
- sizeof(disk_lastobjid),
- &file->f_pos);
- if (retval != sizeof(disk_lastobjid)) {
- CDEBUG(D_INODE,"OBD filter: error writing lastobjid\n");
- filp_close(file, 0);
- GOTO(out_O_mode, rc = -EIO);
- }
- } else {
- __u64 disk_lastobjid;
- ssize_t retval = file->f_op->read(file, (char *)&disk_lastobjid,
- sizeof(disk_lastobjid),
- &file->f_pos);
- if (retval != sizeof(disk_lastobjid)) {
- CDEBUG(D_INODE,"OBD filter: error reading lastobjid\n");
- filp_close(file, 0);
- GOTO(out_O_mode, rc = -EIO);
- }
- lastobjid = le64_to_cpu(disk_lastobjid);
- }
- filter->fo_lastobjid = lastobjid;
- filp_close(file, 0);
-
- rc = 0;
- out:
- pop_ctxt(&saved, &filter->fo_ctxt, NULL);
-
- return(rc);
-
-out_O_mode:
- while (mode-- > 0) {
- struct dentry *dentry = filter->fo_dentry_O_mode[mode];
- if (dentry) {
- f_dput(dentry);
- filter->fo_dentry_O_mode[mode] = NULL;
- }
- }
-out_O:
- f_dput(filter->fo_dentry_O);
- filter->fo_dentry_O = NULL;
- goto out;
-}
-
-/* cleanup the filter: write last used object id to status file */
-static void filter_post(struct obd_device *obd)
-{
- struct obd_run_ctxt saved;
- struct filter_obd *filter = &obd->u.filter;
- __u64 disk_lastobjid;
- long rc;
- struct file *file;
- int mode;
-
- push_ctxt(&saved, &filter->fo_ctxt, NULL);
- file = filp_open("D/status", O_RDWR | O_CREAT, 0700);
- if (IS_ERR(file)) {
- CERROR("OBD filter: cannot create status file\n");
- goto out;
- }
-
- file->f_pos = 0;
- disk_lastobjid = cpu_to_le64(filter->fo_lastobjid);
- rc = file->f_op->write(file, (char *)&disk_lastobjid,
- sizeof(disk_lastobjid), &file->f_pos);
- if (rc != sizeof(disk_lastobjid))
- CERROR("OBD filter: error writing lastobjid: rc = %ld\n", rc);
-
- rc = filp_close(file, NULL);
- if (rc)
- CERROR("OBD filter: cannot close status file: rc = %ld\n", rc);
-
- for (mode = 0; mode < (S_IFMT >> S_SHIFT); mode++) {
- struct dentry *dentry = filter->fo_dentry_O_mode[mode];
- if (dentry) {
- f_dput(dentry);
- filter->fo_dentry_O_mode[mode] = NULL;
- }
- }
- f_dput(filter->fo_dentry_O);
-out:
- pop_ctxt(&saved, &filter->fo_ctxt, NULL);
-}
-
-
-static __u64 filter_next_id(struct obd_device *obd)
-{
- obd_id id;
-
- spin_lock(&obd->u.filter.fo_objidlock);
- id = ++obd->u.filter.fo_lastobjid;
- spin_unlock(&obd->u.filter.fo_objidlock);
-
- /* FIXME: write the lastobjid to disk here */
- return id;
-}
-
-/* how to get files, dentries, inodes from object id's */
-/* parent i_sem is already held if needed for exclusivity */
-static struct dentry *filter_fid2dentry(struct obd_device *obd,
- struct dentry *dparent,
- __u64 id, __u32 type, int locked)
-{
- struct super_block *sb = obd->u.filter.fo_sb;
- struct dentry *dchild;
- char name[32];
- int len;
- ENTRY;
-
- if (!sb || !sb->s_dev) {
- CERROR("fatal: device not initialized.\n");
- RETURN(ERR_PTR(-ENXIO));
- }
-
- if (id == 0) {
- CERROR("fatal: invalid object #0\n");
- LBUG();
- RETURN(ERR_PTR(-ESTALE));
- }
-
- if (!(type & S_IFMT)) {
- CERROR("OBD %s, object "LPU64" has bad type: %o\n",
- __FUNCTION__, id, type);
- RETURN(ERR_PTR(-EINVAL));
- }
-
- len = sprintf(name, LPU64, id);
- CDEBUG(D_INODE, "opening object O/%s/%s\n", obd_mode_to_type(type),
- name);
- if (!locked)
- down(&dparent->d_inode->i_sem);
- dchild = lookup_one_len(name, dparent, len);
- if (!locked)
- up(&dparent->d_inode->i_sem);
- if (IS_ERR(dchild)) {
- CERROR("child lookup error %ld\n", PTR_ERR(dchild));
- RETURN(dchild);
- }
-
- CDEBUG(D_INODE, "got child obj O/%s/%s: %p, count = %d\n",
- obd_mode_to_type(type), name, dchild,
- atomic_read(&dchild->d_count));
-
- LASSERT(atomic_read(&dchild->d_count) > 0);
-
- RETURN(dchild);
-}
-
-static inline struct dentry *filter_parent(struct obd_device *obd,
- obd_mode mode)
-{
- struct filter_obd *filter = &obd->u.filter;
-
- return filter->fo_dentry_O_mode[(mode & S_IFMT) >> S_SHIFT];
-}
-
-static struct file *filter_obj_open(struct obd_export *export,
- __u64 id, __u32 type)
-{
- struct filter_obd *filter = &export->exp_obd->u.filter;
- struct super_block *sb = filter->fo_sb;
- struct dentry *dentry;
- struct filter_export_data *fed = &export->exp_filter_data;
- struct filter_dentry_data *fdd;
- struct filter_file_data *ffd;
- struct obd_run_ctxt saved;
- char name[24];
- struct file *file;
- ENTRY;
-
- if (!sb || !sb->s_dev) {
- CERROR("fatal: device not initialized.\n");
- RETURN(ERR_PTR(-ENXIO));
- }
-
- if (!id) {
- CERROR("fatal: invalid obdo "LPU64"\n", id);
- RETURN(ERR_PTR(-ESTALE));
- }
-
- if (!(type & S_IFMT)) {
- CERROR("OBD %s, object "LPU64" has bad type: %o\n",
- __FUNCTION__, id, type);
- RETURN(ERR_PTR(-EINVAL));
- }
-
- ffd = kmem_cache_alloc(filter_open_cache, SLAB_KERNEL);
- if (!ffd) {
- CERROR("obdfilter: out of memory\n");
- RETURN(ERR_PTR(-ENOMEM));
- }
-
- /* We preallocate this to avoid blocking while holding fo_fddlock */
- fdd = kmem_cache_alloc(filter_dentry_cache, SLAB_KERNEL);
- if (!fdd) {
- CERROR("obdfilter: out of memory\n");
- GOTO(out_ffd, file = ERR_PTR(-ENOMEM));
- }
-
- filter_id(name, id, type);
- push_ctxt(&saved, &filter->fo_ctxt, NULL);
- file = filp_open(name, O_RDWR | O_LARGEFILE, 0 /* type? */);
- pop_ctxt(&saved, &filter->fo_ctxt, NULL);
-
- if (IS_ERR(file)) {
- CERROR("error opening %s: rc %d\n", name, PTR_ERR(file));
- GOTO(out_fdd, file);
- }
-
- dentry = file->f_dentry;
- spin_lock(&filter->fo_fddlock);
- if (dentry->d_fsdata) {
- spin_unlock(&filter->fo_fddlock);
- kmem_cache_free(filter_dentry_cache, fdd);
- fdd = dentry->d_fsdata;
- LASSERT(kmem_cache_validate(filter_dentry_cache, fdd));
- /* should only happen during client recovery */
- if (fdd->fdd_flags & FILTER_FLAG_DESTROY)
- CDEBUG(D_INODE,"opening destroyed object "LPX64"\n",id);
- atomic_inc(&fdd->fdd_open_count);
- } else {
- atomic_set(&fdd->fdd_open_count, 1);
- fdd->fdd_flags = 0;
- /* If this is racy, then we can use {cmp}xchg and atomic_add */
- dentry->d_fsdata = fdd;
- spin_unlock(&filter->fo_fddlock);
- }
-
- get_random_bytes(&ffd->ffd_servercookie, sizeof(ffd->ffd_servercookie));
- ffd->ffd_file = file;
- file->private_data = ffd;
-
- if (!dentry->d_op)
- dentry->d_op = &filter_dops;
- else
- LASSERT(dentry->d_op == &filter_dops);
-
- spin_lock(&fed->fed_lock);
- list_add(&ffd->ffd_export_list, &fed->fed_open_head);
- spin_unlock(&fed->fed_lock);
-
- CDEBUG(D_INODE, "opened objid "LPX64": rc = %p\n", id, file);
-
-out:
- RETURN(file);
-
-out_fdd:
- kmem_cache_free(filter_dentry_cache, fdd);
-out_ffd:
- ffd->ffd_servercookie = DEAD_HANDLE_MAGIC;
- kmem_cache_free(filter_open_cache, ffd);
- goto out;
-}
-
-/* Caller must hold i_sem on dir_dentry->d_inode */
-static int filter_destroy_internal(struct obd_device *obd,
- struct dentry *dir_dentry,
- struct dentry *object_dentry)
-{
- struct obd_run_ctxt saved;
- struct inode *inode = object_dentry->d_inode;
- int rc;
- ENTRY;
-
- if (inode->i_nlink != 1 || atomic_read(&inode->i_count) != 1) {
- CERROR("destroying objid %*s nlink = %d, count = %d\n",
- object_dentry->d_name.len,
- object_dentry->d_name.name,
- inode->i_nlink, atomic_read(&inode->i_count));
- }
-
- push_ctxt(&saved, &obd->u.filter.fo_ctxt, NULL);
- rc = vfs_unlink(dir_dentry->d_inode, object_dentry);
- /* XXX unlink from PENDING directory now too */
- pop_ctxt(&saved, &obd->u.filter.fo_ctxt, NULL);
-
- if (rc)
- CERROR("error unlinking objid %*s: rc %d\n",
- object_dentry->d_name.len,
- object_dentry->d_name.name, rc);
-
- RETURN(rc);
-}
-
-static int filter_close_internal(struct obd_device *obd,
- struct filter_file_data *ffd)
-{
- struct file *filp = ffd->ffd_file;
- struct dentry *object_dentry = dget(filp->f_dentry);
- struct filter_dentry_data *fdd = object_dentry->d_fsdata;
- int rc, rc2 = 0;
- ENTRY;
-
- LASSERT(filp->private_data == ffd);
- LASSERT(fdd);
-
- rc = filp_close(filp, 0);
-
- if (atomic_dec_and_test(&fdd->fdd_open_count) &&
- fdd->fdd_flags & FILTER_FLAG_DESTROY) {
- struct dentry *dir_dentry = filter_parent(obd, S_IFREG);
-
- down(&dir_dentry->d_inode->i_sem);
- rc2 = filter_destroy_internal(obd, dir_dentry, object_dentry);
- if (rc2 && !rc)
- rc = rc2;
- up(&dir_dentry->d_inode->i_sem);
- }
-
- f_dput(object_dentry);
- kmem_cache_free(filter_open_cache, ffd);
-
- RETURN(rc);
-}
-
-/* obd methods */
-static int filter_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- struct obd_export *exp;
- int rc;
-
- ENTRY;
- MOD_INC_USE_COUNT;
- rc = class_connect(conn, obd, cluuid);
- if (rc)
- GOTO(out_dec, rc);
- exp = class_conn2export(conn);
- LASSERT(exp);
-
- INIT_LIST_HEAD(&exp->exp_filter_data.fed_open_head);
- spin_lock_init(&exp->exp_filter_data.fed_lock);
-out:
- RETURN(rc);
-
-out_dec:
- MOD_DEC_USE_COUNT;
- goto out;
-}
-
-static int filter_disconnect(struct lustre_handle *conn)
-{
- struct obd_export *exp = class_conn2export(conn);
- struct filter_export_data *fed;
- int rc;
- ENTRY;
-
- LASSERT(exp);
- fed = &exp->exp_filter_data;
- spin_lock(&fed->fed_lock);
- while (!list_empty(&fed->fed_open_head)) {
- struct filter_file_data *ffd;
-
- ffd = list_entry(fed->fed_open_head.next, typeof(*ffd),
- ffd_export_list);
- list_del(&ffd->ffd_export_list);
- spin_unlock(&fed->fed_lock);
-
- CERROR("force closing file %*s on disconnect\n",
- ffd->ffd_file->f_dentry->d_name.len,
- ffd->ffd_file->f_dentry->d_name.name);
-
- filter_close_internal(exp->exp_obd, ffd);
- spin_lock(&fed->fed_lock);
- }
- spin_unlock(&fed->fed_lock);
-
- ldlm_cancel_locks_for_export(exp);
- rc = class_disconnect(conn);
- if (!rc)
- MOD_DEC_USE_COUNT;
-
- /* XXX cleanup preallocated inodes */
- RETURN(rc);
-}
-
-/* mount the file system (secretly) */
-static int filter_setup(struct obd_device *obd, obd_count len, void *buf)
-{
- struct obd_ioctl_data* data = buf;
- struct filter_obd *filter;
- struct vfsmount *mnt;
- int err = 0;
- ENTRY;
-
- if (!data->ioc_inlbuf1 || !data->ioc_inlbuf2)
- RETURN(-EINVAL);
-
- MOD_INC_USE_COUNT;
- mnt = do_kern_mount(data->ioc_inlbuf2, 0, data->ioc_inlbuf1, NULL);
- err = PTR_ERR(mnt);
- if (IS_ERR(mnt))
- GOTO(err_dec, err);
-
- filter = &obd->u.filter;;
- filter->fo_vfsmnt = mnt;
- filter->fo_fstype = strdup(data->ioc_inlbuf2);
- filter->fo_sb = mnt->mnt_root->d_inode->i_sb;
- CERROR("%s: mnt is %p\n", data->ioc_inlbuf1, filter->fo_vfsmnt);
- /* XXX is this even possible if do_kern_mount succeeded? */
- if (!filter->fo_sb)
- GOTO(err_kfree, err = -ENODEV);
-
- OBD_SET_CTXT_MAGIC(&filter->fo_ctxt);
- filter->fo_ctxt.pwdmnt = mnt;
- filter->fo_ctxt.pwd = mnt->mnt_root;
- filter->fo_ctxt.fs = get_ds();
-
- err = filter_prep(obd);
- if (err)
- GOTO(err_kfree, err);
- spin_lock_init(&filter->fo_fddlock);
- spin_lock_init(&filter->fo_objidlock);
- INIT_LIST_HEAD(&filter->fo_export_list);
-
- obd->obd_namespace =
- ldlm_namespace_new("filter-tgt", LDLM_NAMESPACE_SERVER);
- if (obd->obd_namespace == NULL)
- LBUG();
-
- ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
- "filter_ldlm_cb_client", &obd->obd_ldlm_client);
-
- RETURN(0);
-
-err_kfree:
- kfree(filter->fo_fstype);
- unlock_kernel();
- mntput(filter->fo_vfsmnt);
- filter->fo_sb = 0;
- lock_kernel();
-
-err_dec:
- MOD_DEC_USE_COUNT;
- return err;
-}
-
-
-static int filter_cleanup(struct obd_device *obd)
-{
- struct super_block *sb;
- ENTRY;
-
- if (!list_empty(&obd->obd_exports)) {
- CERROR("still has clients!\n");
- class_disconnect_all(obd);
- if (!list_empty(&obd->obd_exports)) {
- CERROR("still has exports after forced cleanup?\n");
- RETURN(-EBUSY);
- }
- }
-
- ldlm_namespace_free(obd->obd_namespace);
-
- sb = obd->u.filter.fo_sb;
- if (!obd->u.filter.fo_sb)
- RETURN(0);
-
- filter_post(obd);
-
- shrink_dcache_parent(sb->s_root);
- unlock_kernel();
- mntput(obd->u.filter.fo_vfsmnt);
- obd->u.filter.fo_sb = 0;
- kfree(obd->u.filter.fo_fstype);
-
- lock_kernel();
-
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-
-static void filter_from_inode(struct obdo *oa, struct inode *inode, int valid)
-{
- int type = oa->o_mode & S_IFMT;
- ENTRY;
-
- CDEBUG(D_INFO, "src inode %ld (%p), dst obdo %ld valid 0x%08x\n",
- inode->i_ino, inode, (long)oa->o_id, valid);
- /* Don't copy the inode number in place of the object ID */
- obdo_from_inode(oa, inode, valid);
- oa->o_mode &= ~S_IFMT;
- oa->o_mode |= type;
-
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
- obd_rdev rdev = kdev_t_to_nr(inode->i_rdev);
- oa->o_rdev = rdev;
- oa->o_valid |= OBD_MD_FLRDEV;
- }
-
- EXIT;
-}
-
-static struct filter_file_data *filter_handle2ffd(struct lustre_handle *handle)
-{
- struct filter_file_data *ffd = NULL;
- ENTRY;
-
- if (!handle || !handle->addr)
- RETURN(NULL);
-
- ffd = (struct filter_file_data *)(unsigned long)(handle->addr);
- if (!kmem_cache_validate(filter_open_cache, (void *)ffd))
- RETURN(NULL);
-
- if (ffd->ffd_servercookie != handle->cookie)
- RETURN(NULL);
-
- LASSERT(ffd->ffd_file->private_data == ffd);
- RETURN(ffd);
-}
-
-static struct dentry *__filter_oa2dentry(struct lustre_handle *conn,
- struct obdo *oa, int locked,char *what)
-{
- struct dentry *dentry = NULL;
-
- if (oa->o_valid & OBD_MD_FLHANDLE) {
- struct lustre_handle *ost_handle = obdo_handle(oa);
- struct filter_file_data *ffd = filter_handle2ffd(ost_handle);
-
- if (ffd)
- dentry = dget(ffd->ffd_file->f_dentry);
- }
-
- if (!dentry) {
- struct obd_device *obd = class_conn2obd(conn);
- if (!obd) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- RETURN(ERR_PTR(-EINVAL));
- }
- dentry = filter_fid2dentry(obd, filter_parent(obd, oa->o_mode),
- oa->o_id, oa->o_mode, locked);
- }
-
- if (IS_ERR(dentry)) {
- CERROR("%s error looking up object: "LPX64"\n", what, oa->o_id);
- RETURN(dentry);
- }
-
- if (!dentry->d_inode) {
- CERROR("%s on non-existent object: "LPX64"\n", what, oa->o_id);
- f_dput(dentry);
- RETURN(ERR_PTR(-ENOENT));
- }
-
- return dentry;
-}
-
-#define filter_oa2dentry(conn, oa, locked) __filter_oa2dentry(conn, oa, locked,\
- __FUNCTION__)
-
-static int filter_getattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- struct dentry *dentry = NULL;
- int rc = 0;
- ENTRY;
-
- dentry = filter_oa2dentry(conn, oa, 0);
- if (IS_ERR(dentry))
- RETURN(PTR_ERR(dentry));
-
- filter_from_inode(oa, dentry->d_inode, oa->o_valid);
-
- f_dput(dentry);
- RETURN(rc);
-}
-
-static int filter_setattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- struct obd_run_ctxt saved;
- struct obd_device *obd = class_conn2obd(conn);
- struct dentry *dentry;
- struct iattr iattr;
- struct inode *inode;
- int rc;
- ENTRY;
-
- dentry = filter_oa2dentry(conn, oa, 0);
-
- if (IS_ERR(dentry))
- RETURN(PTR_ERR(dentry));
-
- iattr_from_obdo(&iattr, oa, oa->o_valid);
- iattr.ia_mode = (iattr.ia_mode & ~S_IFMT) | S_IFREG;
- inode = dentry->d_inode;
-
- lock_kernel();
- if (iattr.ia_valid & ATTR_SIZE)
- down(&inode->i_sem);
- push_ctxt(&saved, &obd->u.filter.fo_ctxt, NULL);
- if (inode->i_op->setattr)
- rc = inode->i_op->setattr(dentry, &iattr);
- else
- rc = inode_setattr(inode, &iattr);
- pop_ctxt(&saved, &obd->u.filter.fo_ctxt, NULL);
- if (iattr.ia_valid & ATTR_SIZE) {
- up(&inode->i_sem);
- oa->o_valid = OBD_MD_FLBLOCKS | OBD_MD_FLCTIME | OBD_MD_FLMTIME;
- obdo_from_inode(oa, inode, oa->o_valid);
- }
- unlock_kernel();
-
- f_dput(dentry);
- RETURN(rc);
-}
-
-static int filter_open(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea)
-{
- struct obd_export *export;
- struct lustre_handle *handle;
- struct filter_file_data *ffd;
- struct file *filp;
- int rc = 0;
- ENTRY;
-
- export = class_conn2export(conn);
- if (!export) {
- CDEBUG(D_IOCTL, "fatal: invalid client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- filp = filter_obj_open(export, oa->o_id, oa->o_mode);
- if (IS_ERR(filp))
- GOTO(out, rc = PTR_ERR(filp));
-
- filter_from_inode(oa, filp->f_dentry->d_inode, oa->o_valid);
-
- ffd = filp->private_data;
- handle = obdo_handle(oa);
- handle->addr = (__u64)(unsigned long)ffd;
- handle->cookie = ffd->ffd_servercookie;
- oa->o_valid |= OBD_MD_FLHANDLE;
- EXIT;
-out:
- return rc;
-} /* filter_open */
-
-static int filter_close(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea)
-{
- struct obd_export *exp;
- struct filter_file_data *ffd;
- struct filter_export_data *fed;
- int rc;
- ENTRY;
-
- exp = class_conn2export(conn);
- if (!exp) {
- CDEBUG(D_IOCTL, "fatal: invalid client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- if (!(oa->o_valid & OBD_MD_FLHANDLE)) {
- CERROR("no handle for close of objid "LPX64"\n", oa->o_id);
- RETURN(-EINVAL);
- }
-
- ffd = filter_handle2ffd(obdo_handle(oa));
- if (!ffd) {
- struct lustre_handle *handle = obdo_handle(oa);
- CERROR("bad handle ("LPX64") or cookie ("LPX64") for close\n",
- handle->addr, handle->cookie);
- RETURN(-ESTALE);
- }
-
- fed = &exp->exp_filter_data;
- spin_lock(&fed->fed_lock);
- list_del(&ffd->ffd_export_list);
- spin_unlock(&fed->fed_lock);
-
- rc = filter_close_internal(exp->exp_obd, ffd);
-
- RETURN(rc);
-} /* filter_close */
-
-static int filter_create(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md **ea)
-{
- struct obd_device *obd = class_conn2obd(conn);
- char name[64];
- struct obd_run_ctxt saved;
- struct dentry *new;
- struct iattr;
- ENTRY;
-
- if (!obd) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- return -EINVAL;
- }
-
- if (!(oa->o_mode & S_IFMT)) {
- CERROR("OBD %s, object "LPU64" has bad type: %o\n",
- __FUNCTION__, oa->o_id, oa->o_mode);
- return -ENOENT;
- }
-
- oa->o_id = filter_next_id(obd);
-
- //filter_id(name, oa->o_id, oa->o_mode);
- sprintf(name, LPU64, oa->o_id);
- push_ctxt(&saved, &obd->u.filter.fo_ctxt, NULL);
- new = simple_mknod(filter_parent(obd, oa->o_mode), name, oa->o_mode);
- pop_ctxt(&saved, &obd->u.filter.fo_ctxt, NULL);
- if (IS_ERR(new)) {
- CERROR("Error mknod obj %s, err %ld\n", name, PTR_ERR(new));
- return -ENOENT;
- }
-
- /* Set flags for fields we have set in the inode struct */
- oa->o_valid = OBD_MD_FLID | OBD_MD_FLBLKSZ | OBD_MD_FLBLOCKS |
- OBD_MD_FLMTIME | OBD_MD_FLATIME | OBD_MD_FLCTIME;
- filter_from_inode(oa, new->d_inode, oa->o_valid);
- f_dput(new);
-
- return 0;
-}
-
-static int filter_destroy(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct dentry *dir_dentry, *object_dentry;
- struct filter_dentry_data *fdd;
- int rc;
- ENTRY;
-
- if (!obd) {
- CERROR("invalid client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- CDEBUG(D_INODE, "destroying objid "LPX64"\n", oa->o_id);
-
- dir_dentry = filter_parent(obd, oa->o_mode);
- down(&dir_dentry->d_inode->i_sem);
-
- object_dentry = filter_oa2dentry(conn, oa, 1);
- if (IS_ERR(object_dentry))
- GOTO(out, rc = -ENOENT);
-
- fdd = object_dentry->d_fsdata;
- if (fdd && atomic_read(&fdd->fdd_open_count)) {
- if (!(fdd->fdd_flags & FILTER_FLAG_DESTROY)) {
- fdd->fdd_flags |= FILTER_FLAG_DESTROY;
- /* XXX put into PENDING directory in case of crash */
- CDEBUG(D_INODE,
- "defer destroy of %dx open objid "LPX64"\n",
- atomic_read(&fdd->fdd_open_count), oa->o_id);
- } else
- CDEBUG(D_INODE,
- "repeat destroy of %dx open objid "LPX64"\n",
- atomic_read(&fdd->fdd_open_count), oa->o_id);
- GOTO(out_dput, rc = 0);
- }
-
- rc = filter_destroy_internal(obd, dir_dentry, object_dentry);
-out_dput:
- f_dput(object_dentry);
-
- EXIT;
-out:
- up(&dir_dentry->d_inode->i_sem);
- return rc;
-}
-
-/* NB count and offset are used for punch, but not truncate */
-static int filter_truncate(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *lsm,
- obd_off start, obd_off end)
-{
- int error;
- ENTRY;
-
- if (end != OBD_OBJECT_EOF)
- CERROR("PUNCH not supported, only truncate works\n");
-
- CDEBUG(D_INODE, "calling truncate for object "LPX64", valid = %x, "
- "o_size = "LPD64"\n", oa->o_id, oa->o_valid, start);
- oa->o_size = start;
- error = filter_setattr(conn, oa, NULL);
- RETURN(error);
-}
-
-static int filter_pgcache_brw(int cmd, struct lustre_handle *conn,
- struct lov_stripe_md *lsm, obd_count oa_bufs,
- struct brw_page *pga, struct obd_brw_set *set)
-{
- struct obd_export *export = class_conn2export(conn);
- struct obd_run_ctxt saved;
- struct super_block *sb;
- int pnum; /* index to pages (bufs) */
- unsigned long retval;
- int error;
- struct file *file;
- int pg;
- ENTRY;
-
- if (!export) {
- CDEBUG(D_IOCTL, "invalid client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- sb = export->exp_obd->u.filter.fo_sb;
- push_ctxt(&saved, &export->exp_obd->u.filter.fo_ctxt, NULL);
- pnum = 0; /* pnum indexes buf 0..num_pages */
-
- file = filter_obj_open(export, lsm->lsm_object_id, S_IFREG);
- if (IS_ERR(file))
- GOTO(out, retval = PTR_ERR(file));
-
- /* count doubles as retval */
- for (pg = 0; pg < oa_bufs; pg++) {
- CDEBUG(D_INODE, "OP %d obdo pgno: (%d) (%ld,"LPU64
- ") off count ("LPU64",%d)\n",
- cmd, pnum, file->f_dentry->d_inode->i_ino,
- pga[pnum].off >> PAGE_CACHE_SHIFT, pga[pnum].off,
- (int)pga[pnum].count);
- if (cmd & OBD_BRW_WRITE) {
- loff_t off;
- char *buffer;
- off = pga[pnum].off;
- buffer = kmap(pga[pnum].pg);
- retval = file->f_op->write(file, buffer,
- pga[pnum].count,
- &off);
- kunmap(pga[pnum].pg);
- CDEBUG(D_INODE, "retval %ld\n", retval);
- } else {
- loff_t off = pga[pnum].off;
- char *buffer = kmap(pga[pnum].pg);
-
- if (off >= file->f_dentry->d_inode->i_size) {
- memset(buffer, 0, pga[pnum].count);
- retval = pga[pnum].count;
- } else {
- retval = file->f_op->read(file, buffer,
- pga[pnum].count, &off);
- }
- kunmap(pga[pnum].pg);
-
- if (retval != pga[pnum].count) {
- filp_close(file, 0);
- GOTO(out, retval = -EIO);
- }
- CDEBUG(D_INODE, "retval %ld\n", retval);
- }
- pnum++;
- }
- /* sizes and blocks are set by generic_file_write */
- /* ctimes/mtimes will follow with a setattr call */
- filp_close(file, 0);
-
- /* XXX: do something with callback if it is set? */
-
- EXIT;
-out:
- pop_ctxt(&saved, &export->exp_obd->u.filter.fo_ctxt, NULL);
- error = (retval >= 0) ? 0 : retval;
- return error;
-}
-
-/*
- * Calculate the number of buffer credits needed to write multiple pages in
- * a single ext3/extN transaction. No, this shouldn't be here, but as yet
- * ext3 doesn't have a nice API for calculating this sort of thing in advance.
- *
- * See comment above ext3_writepage_trans_blocks for details. We assume
- * no data journaling is being done, but it does allow for all of the pages
- * being non-contiguous. If we are guaranteed contiguous pages we could
- * reduce the number of (d)indirect blocks a lot.
- *
- * With N blocks per page and P pages, for each inode we have at most:
- * N*P indirect
- * min(N*P, blocksize/4 + 1) dindirect blocks
- * 1 tindirect
- *
- * For the entire filesystem, we have at most:
- * min(sum(nindir + P), ngroups) bitmap blocks (from the above)
- * min(sum(nindir + P), gdblocks) group descriptor blocks (from the above)
- * 1 inode block
- * 1 superblock
- * 2 * EXT3_SINGLEDATA_TRANS_BLOCKS for the quota files
- */
-static int ext3_credits_needed(struct super_block *sb, int objcount,
- struct obd_ioobj *obj)
-{
- struct obd_ioobj *o = obj;
- int blockpp = 1 << (PAGE_CACHE_SHIFT - sb->s_blocksize_bits);
- int addrpp = EXT3_ADDR_PER_BLOCK(sb) * blockpp;
- int nbitmaps = 0;
- int ngdblocks = 0;
- int needed = objcount + 1;
- int i;
-
- for (i = 0; i < objcount; i++, o++) {
- int nblocks = o->ioo_bufcnt * blockpp;
- int ndindirect = min(nblocks, addrpp + 1);
- int nindir = nblocks + ndindirect + 1;
-
- nbitmaps += nindir + nblocks;
- ngdblocks += nindir + nblocks;
-
- needed += nindir;
- }
-
- /* Assumes ext3 and extN have same sb_info layout at the start. */
- if (nbitmaps > EXT3_SB(sb)->s_groups_count)
- nbitmaps = EXT3_SB(sb)->s_groups_count;
- if (ngdblocks > EXT3_SB(sb)->s_gdb_count)
- ngdblocks = EXT3_SB(sb)->s_gdb_count;
-
- needed += nbitmaps + ngdblocks;
-
-#ifdef CONFIG_QUOTA
- /* We assume that there will be 1 bit set in s_dquot.flags for each
- * quota file that is active. This is at least true for now.
- */
- needed += hweight32(sb_any_quota_enabled(sb)) *
- EXT3_SINGLEDATA_TRANS_BLOCKS;
-#endif
-
- return needed;
-}
-
-/* We have to start a huge journal transaction here to hold all of the
- * metadata for the pages being written here. This is necessitated by
- * the fact that we do lots of prepare_write operations before we do
- * any of the matching commit_write operations, so even if we split
- * up to use "smaller" transactions none of them could complete until
- * all of them were opened. By having a single journal transaction,
- * we eliminate duplicate reservations for common blocks like the
- * superblock and group descriptors or bitmaps.
- *
- * We will start the transaction here, but each prepare_write will
- * add a refcount to the transaction, and each commit_write will
- * remove a refcount. The transaction will be closed when all of
- * the pages have been written.
- */
-static void *ext3_filter_journal_start(struct filter_obd *filter,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_remote *nb)
-{
- journal_t *journal = NULL;
- handle_t *handle = NULL;
- int needed;
-
- /* It appears that some kernels have different values for
- * EXT*_MAX_GROUP_LOADED (either 8 or 32), so we cannot
- * assume anything after s_inode_bitmap_number is the same.
- */
- if (!strcmp(filter->fo_fstype, "ext3"))
- journal = EXT3_SB(filter->fo_sb)->s_journal;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- else if (!strcmp(filter->fo_fstype, "extN"))
- journal = EXTN_SB(filter->fo_sb)->s_journal;
-#endif
- needed = ext3_credits_needed(filter->fo_sb, objcount, obj);
-
- /* The number of blocks we could _possibly_ dirty can very large.
- * We reduce our request if it is absurd (and we couldn't get that
- * many credits for a single handle anyways).
- *
- * At some point we have to limit the size of I/Os sent at one time,
- * increase the size of the journal, or we have to calculate the
- * actual journal requirements more carefully by checking all of
- * the blocks instead of being maximally pessimistic. It remains to
- * be seen if this is a real problem or not.
- */
- if (needed > journal->j_max_transaction_buffers) {
- CERROR("want too many journal credits (%d) using %d instead\n",
- needed, journal->j_max_transaction_buffers);
- needed = journal->j_max_transaction_buffers;
- }
-
- lock_kernel();
- handle = journal_start(journal, needed);
- unlock_kernel();
- if (IS_ERR(handle))
- CERROR("can't get handle for %d credits: rc = %ld\n", needed,
- PTR_ERR(handle));
-
- return(handle);
-}
-
-static void *filter_journal_start(void **journal_save,
- struct filter_obd *filter,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_remote *nb)
-{
- void *handle = NULL;
-
- /* This may not be necessary - we probably never have a
- * transaction started when we enter here, so we can
- * remove the saving of the journal state entirely.
- * For now leave it in just to see if it ever happens.
- */
- *journal_save = current->journal_info;
- if (*journal_save) {
- CERROR("Already have handle %p???\n", *journal_save);
- LBUG();
- current->journal_info = NULL;
- }
-
- if (!strcmp(filter->fo_fstype, "ext3") ||
- !strcmp(filter->fo_fstype, "extN"))
- handle = ext3_filter_journal_start(filter, objcount, obj,
- niocount, nb);
- return handle;
-}
-
-static int ext3_filter_journal_stop(void *handle)
-{
- int rc;
-
- /* We got a refcount on the handle for each call to prepare_write,
- * so we can drop the "parent" handle here to avoid the need for
- * osc to call back into filterobd to close the handle. The
- * remaining references will be dropped in commit_write.
- */
- lock_kernel();
- rc = journal_stop((handle_t *)handle);
- unlock_kernel();
-
- return rc;
-}
-
-static int filter_journal_stop(void *journal_save, struct filter_obd *filter,
- void *handle)
-{
- int rc = 0;
-
- if (!strcmp(filter->fo_fstype, "ext3") ||
- !strcmp(filter->fo_fstype, "extN"))
- rc = ext3_filter_journal_stop(handle);
-
- if (rc)
- CERROR("error on journal stop: rc = %d\n", rc);
-
- current->journal_info = journal_save;
-
- return rc;
-}
-
-static inline void lustre_put_page(struct page *page)
-{
- kunmap(page);
- page_cache_release(page);
-}
-
-
-static struct page *
-lustre_get_page_read(struct inode *inode, struct niobuf_remote *rnb)
-{
- unsigned long index = rnb->offset >> PAGE_SHIFT;
- struct address_space *mapping = inode->i_mapping;
- struct page *page;
- int rc;
-
- page = read_cache_page(mapping, index,
- (filler_t*)mapping->a_ops->readpage, NULL);
- if (!IS_ERR(page)) {
- wait_on_page(page);
- kmap(page);
- if (!PageUptodate(page)) {
- CERROR("page index %lu not uptodate\n", index);
- GOTO(err_page, rc = -EIO);
- }
- if (PageError(page)) {
- CERROR("page index %lu has error\n", index);
- GOTO(err_page, rc = -EIO);
- }
- }
- return page;
-
-err_page:
- lustre_put_page(page);
- return ERR_PTR(rc);
-}
-
-static struct page *
-lustre_get_page_write(struct inode *inode, unsigned long index)
-{
- struct address_space *mapping = inode->i_mapping;
- struct page *page;
- int rc;
-
- page = grab_cache_page(mapping, index); /* locked page */
-
- if (!IS_ERR(page)) {
- kmap(page);
- /* Note: Called with "O" and "PAGE_SIZE" this is essentially
- * a no-op for most filesystems, because we write the whole
- * page. For partial-page I/O this will read in the page.
- */
- rc = mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE);
- if (rc) {
- CERROR("page index %lu, rc = %d\n", index, rc);
- if (rc != -ENOSPC)
- LBUG();
- GOTO(err_unlock, rc);
- }
- /* XXX not sure if we need this if we are overwriting page */
- if (PageError(page)) {
- CERROR("error on page index %lu, rc = %d\n", index, rc);
- LBUG();
- GOTO(err_unlock, rc = -EIO);
- }
- }
- return page;
-
-err_unlock:
- unlock_page(page);
- lustre_put_page(page);
- return ERR_PTR(rc);
-}
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
-int waitfor_one_page(struct page *page)
-{
- wait_on_page_locked(page);
- return 0;
-}
-#endif
-
-static int lustre_commit_write(struct page *page, unsigned from, unsigned to)
-{
- struct inode *inode = page->mapping->host;
- int err;
-
- err = page->mapping->a_ops->commit_write(NULL, page, from, to);
- if (!err && IS_SYNC(inode))
- err = waitfor_one_page(page);
- //SetPageUptodate(page); // the client commit_write will do this
-
- SetPageReferenced(page);
- unlock_page(page);
- lustre_put_page(page);
- return err;
-}
-
-struct page *filter_get_page_write(struct inode *inode,
- struct niobuf_remote *rnb,
- struct niobuf_local *lnb, int *pglocked)
-{
- unsigned long index = rnb->offset >> PAGE_SHIFT;
- struct address_space *mapping = inode->i_mapping;
-
- struct page *page;
- int rc;
-
- //ASSERT_PAGE_INDEX(index, GOTO(err, rc = -EINVAL));
- if (*pglocked)
- page = grab_cache_page_nowait(mapping, index); /* locked page */
- else
- page = grab_cache_page(mapping, index); /* locked page */
-
-
- /* This page is currently locked, so get a temporary page instead. */
- /* XXX I believe this is a very dangerous thing to do - consider if
- * we had multiple writers for the same file (definitely the case
- * if we are using this codepath). If writer A locks the page,
- * writer B writes to a copy (as here), writer A drops the page
- * lock, and writer C grabs the lock before B does, then B will
- * later overwrite the data from C, even if C had LDLM locked
- * and initiated the write after B did.
- */
- if (!page) {
- unsigned long addr;
- CDEBUG(D_PAGE, "ino %ld page %ld locked\n", inode->i_ino,index);
- addr = __get_free_pages(GFP_KERNEL, 0); /* locked page */
- if (!addr) {
- CERROR("no memory for a temp page\n");
- LBUG();
- GOTO(err, rc = -ENOMEM);
- }
- /* XXX debugging */
- memset((void *)addr, 0xBA, PAGE_SIZE);
- page = virt_to_page(addr);
- kmap(page);
- page->index = index;
- lnb->flags |= N_LOCAL_TEMP_PAGE;
- } else if (!IS_ERR(page)) {
- (*pglocked)++;
- kmap(page);
-
- rc = mapping->a_ops->prepare_write(NULL, page,
- rnb->offset % PAGE_SIZE,
- rnb->len);
- if (rc) {
- CERROR("page index %lu, rc = %d\n", index, rc);
- if (rc != -ENOSPC)
- LBUG();
- GOTO(err_unlock, rc);
- }
- /* XXX not sure if we need this if we are overwriting page */
- if (PageError(page)) {
- CERROR("error on page index %lu, rc = %d\n", index, rc);
- LBUG();
- GOTO(err_unlock, rc = -EIO);
- }
- }
- return page;
-
-err_unlock:
- unlock_page(page);
- lustre_put_page(page);
-err:
- return ERR_PTR(rc);
-}
-
-/*
- * We need to balance prepare_write() calls with commit_write() calls.
- * If the page has been prepared, but we have no data for it, we don't
- * want to overwrite valid data on disk, but we still need to zero out
- * data for space which was newly allocated. Like part of what happens
- * in __block_prepare_write() for newly allocated blocks.
- *
- * XXX currently __block_prepare_write() creates buffers for all the
- * pages, and the filesystems mark these buffers as BH_New if they
- * were newly allocated from disk. We use the BH_New flag similarly.
- */
-static int filter_commit_write(struct page *page, unsigned from, unsigned to,
- int err)
-{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- if (err) {
- unsigned block_start, block_end;
- struct buffer_head *bh, *head = page->buffers;
- unsigned blocksize = head->b_size;
- void *addr = page_address(page);
-
- /* debugging: just seeing if this ever happens */
- CERROR("called filter_commit_write for obj %ld:%ld on err %d\n",
- page->index, page->mapping->host->i_ino, err);
-
- /* Currently one buffer per page, but in the future... */
- for (bh = head, block_start = 0; bh != head || !block_start;
- block_start = block_end, bh = bh->b_this_page) {
- block_end = block_start + blocksize;
- if (buffer_new(bh))
- memset(addr + block_start, 0, blocksize);
- }
- }
-#endif
- return lustre_commit_write(page, from, to);
-}
-
-static int filter_preprw(int cmd, struct lustre_handle *conn,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_remote *nb,
- struct niobuf_local *res, void **desc_private)
-{
- struct obd_run_ctxt saved;
- struct obd_device *obd;
- struct obd_ioobj *o = obj;
- struct niobuf_remote *rnb = nb;
- struct niobuf_local *lnb = res;
- void *journal_save = NULL;
- int pglocked = 0;
- int rc = 0;
- int i;
- ENTRY;
-
- obd = class_conn2obd(conn);
- if (!obd) {
- CDEBUG(D_IOCTL, "invalid client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
- memset(res, 0, sizeof(*res) * niocount);
-
- push_ctxt(&saved, &obd->u.filter.fo_ctxt, NULL);
-
- if (cmd & OBD_BRW_WRITE) {
- *desc_private = filter_journal_start(&journal_save,
- &obd->u.filter,
- objcount, obj, niocount,
- nb);
- if (IS_ERR(*desc_private))
- GOTO(out_ctxt, rc = PTR_ERR(*desc_private));
- }
-
- obd_kmap_get(niocount, 1);
-
- for (i = 0; i < objcount; i++, o++) {
- struct dentry *dentry;
- struct inode *inode;
- int j;
-
- dentry = filter_fid2dentry(obd, filter_parent(obd, S_IFREG),
- o->ioo_id, S_IFREG, 0);
- if (IS_ERR(dentry))
- GOTO(out_clean, rc = PTR_ERR(dentry));
- inode = dentry->d_inode;
- if (!inode) {
- CERROR("trying to BRW to non-existent file "LPU64"\n",
- o->ioo_id);
- f_dput(dentry);
- GOTO(out_clean, rc = -ENOENT);
- }
-
- for (j = 0; j < o->ioo_bufcnt; j++, rnb++, lnb++) {
- struct page *page;
-
- if (j == 0)
- lnb->dentry = dentry;
- else
- lnb->dentry = dget(dentry);
-
- if (cmd & OBD_BRW_WRITE)
- page = filter_get_page_write(inode, rnb, lnb,
- &pglocked);
- else
- page = lustre_get_page_read(inode, rnb);
-
- if (IS_ERR(page)) {
- f_dput(dentry);
- GOTO(out_clean, rc = PTR_ERR(page));
- }
-
- lnb->addr = page_address(page);
- lnb->offset = rnb->offset;
- lnb->page = page;
- lnb->len = rnb->len;
- }
- }
-
-out_stop:
- if (cmd & OBD_BRW_WRITE) {
- int err = filter_journal_stop(journal_save, &obd->u.filter,
- *desc_private);
- if (!rc)
- rc = err;
- }
-out_ctxt:
- pop_ctxt(&saved, &obd->u.filter.fo_ctxt, NULL);
- RETURN(rc);
-out_clean:
- while (lnb-- > res) {
- CERROR("error cleanup on brw\n");
- f_dput(lnb->dentry);
- if (cmd & OBD_BRW_WRITE)
- filter_commit_write(lnb->page, 0, PAGE_SIZE, rc);
- else
- lustre_put_page(lnb->page);
- }
- obd_kmap_put(niocount);
- goto out_stop;
-}
-
-static int filter_write_locked_page(struct niobuf_local *lnb)
-{
- struct page *lpage;
- int rc;
-
- lpage = lustre_get_page_write(lnb->dentry->d_inode, lnb->page->index);
- if (IS_ERR(lpage)) {
- /* It is highly unlikely that we would ever get an error here.
- * The page we want to get was previously locked, so it had to
- * have already allocated the space, and we were just writing
- * over the same data, so there would be no hole in the file.
- *
- * XXX: possibility of a race with truncate could exist, need
- * to check that. There are no guarantees w.r.t.
- * write order even on a local filesystem, although the
- * normal response would be to return the number of bytes
- * successfully written and leave the rest to the app.
- */
- rc = PTR_ERR(lpage);
- CERROR("error getting locked page index %ld: rc = %d\n",
- lnb->page->index, rc);
- GOTO(out, rc);
- }
-
- /* lpage is kmapped in lustre_get_page_write() above and kunmapped in
- * lustre_commit_write() below, lnb->page was kmapped previously in
- * filter_get_page_write() and kunmapped in lustre_put_page() below.
- */
- memcpy(page_address(lpage), page_address(lnb->page), PAGE_SIZE);
- rc = lustre_commit_write(lpage, 0, PAGE_SIZE);
- if (rc)
- CERROR("error committing locked page %ld: rc = %d\n",
- lnb->page->index, rc);
-out:
- lustre_put_page(lnb->page);
-
- return rc;
-}
-
-static int filter_commitrw(int cmd, struct lustre_handle *conn,
- int objcount, struct obd_ioobj *obj,
- int niocount, struct niobuf_local *res,
- void *private)
-{
- struct obd_run_ctxt saved;
- struct obd_ioobj *o;
- struct niobuf_local *r;
- struct obd_device *obd = class_conn2obd(conn);
- void *journal_save;
- int found_locked = 0;
- int rc = 0;
- int i;
- ENTRY;
-
- push_ctxt(&saved, &obd->u.filter.fo_ctxt, NULL);
- lock_kernel();
- journal_save = current->journal_info;
- LASSERT(!journal_save);
-
- current->journal_info = private;
- unlock_kernel();
- for (i = 0, o = obj, r = res; i < objcount; i++, o++) {
- int j;
- for (j = 0 ; j < o->ioo_bufcnt ; j++, r++) {
- struct page *page = r->page;
-
- if (!page)
- LBUG();
-
- if (r->flags & N_LOCAL_TEMP_PAGE) {
- found_locked++;
- continue;
- }
-
- if (cmd & OBD_BRW_WRITE) {
- int err = filter_commit_write(page, 0,
- r->len, 0);
-
- if (!rc)
- rc = err;
- } else
- lustre_put_page(page);
-
- obd_kmap_put(1);
- f_dput(r->dentry);
- }
- }
- lock_kernel();
- current->journal_info = journal_save;
- unlock_kernel();
-
- if (!found_locked)
- goto out_ctxt;
-
- for (i = 0, o = obj, r = res; i < objcount; i++, o++) {
- int j;
- for (j = 0 ; j < o->ioo_bufcnt ; j++, r++) {
- int err;
- if (!(r->flags & N_LOCAL_TEMP_PAGE))
- continue;
-
- err = filter_write_locked_page(r);
- obd_kmap_put(1);
- if (!rc)
- rc = err;
- f_dput(r->dentry);
- }
- }
-
-out_ctxt:
- pop_ctxt(&saved, &obd->u.filter.fo_ctxt, NULL);
- RETURN(rc);
-}
-
-static int filter_statfs(struct lustre_handle *conn, struct obd_statfs *osfs)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct statfs sfs;
- int rc;
-
- ENTRY;
- rc = vfs_statfs(obd->u.filter.fo_sb, &sfs);
- if (!rc)
- statfs_pack(osfs, &sfs);
-
- return rc;
-}
-
-static int filter_get_info(struct lustre_handle *conn, obd_count keylen,
- void *key, obd_count *vallen, void **val)
-{
- struct obd_device *obd;
- ENTRY;
-
- obd = class_conn2obd(conn);
- if (!obd) {
- CDEBUG(D_IOCTL, "invalid client "LPX64"\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- if ( keylen == strlen("blocksize") &&
- memcmp(key, "blocksize", keylen) == 0 ) {
- *vallen = sizeof(long);
- *val = (void *)(long)obd->u.filter.fo_sb->s_blocksize;
- RETURN(0);
- }
-
- if ( keylen == strlen("blocksize_bits") &&
- memcmp(key, "blocksize_bits", keylen) == 0 ){
- *vallen = sizeof(long);
- *val = (void *)(long)obd->u.filter.fo_sb->s_blocksize_bits;
- RETURN(0);
- }
-
- if ( keylen == strlen("root_ino") &&
- memcmp(key, "root_ino", keylen) == 0 ){
- *vallen = sizeof(obd_id);
- *val = (void *)(obd_id)FILTER_ROOTINO;
- RETURN(0);
- }
-
- CDEBUG(D_IOCTL, "invalid key\n");
- RETURN(-EINVAL);
-}
-
-int filter_copy_data(struct lustre_handle *dst_conn, struct obdo *dst,
- struct lustre_handle *src_conn, struct obdo *src,
- obd_size count, obd_off offset)
-{
- struct page *page;
- struct lov_stripe_md srcmd, dstmd;
- unsigned long index = 0;
- int err = 0;
-
- memset(&srcmd, 0, sizeof(srcmd));
- memset(&dstmd, 0, sizeof(dstmd));
- srcmd.lsm_object_id = src->o_id;
- dstmd.lsm_object_id = dst->o_id;
-
- ENTRY;
- CDEBUG(D_INFO, "src: ino "LPU64" blocks "LPU64", size "LPU64
- ", dst: ino "LPU64"\n",
- src->o_id, src->o_blocks, src->o_size, dst->o_id);
- page = alloc_page(GFP_USER);
- if (page == NULL)
- RETURN(-ENOMEM);
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- while (TryLockPage(page))
- ___wait_on_page(page);
-#else
- wait_on_page_locked(page);
-#endif
-
- /* XXX with brw vector I/O, we could batch up reads and writes here,
- * all we need to do is allocate multiple pages to handle the I/Os
- * and arrays to handle the request parameters.
- */
- while (index < ((src->o_size + PAGE_SIZE - 1) >> PAGE_SHIFT)) {
- struct brw_page pg;
- struct obd_brw_set *set;
-
- set = obd_brw_set_new();
- if (set == NULL) {
- err = -ENOMEM;
- EXIT;
- break;
- }
-
- pg.pg = page;
- pg.count = PAGE_SIZE;
- pg.off = (page->index) << PAGE_SHIFT;
- pg.flag = 0;
-
- page->index = index;
- set->brw_callback = ll_brw_sync_wait;
- err = obd_brw(OBD_BRW_READ, src_conn, &srcmd, 1, &pg, set);
- obd_brw_set_free(set);
- if (err) {
- EXIT;
- break;
- }
-
- set = obd_brw_set_new();
- if (set == NULL) {
- err = -ENOMEM;
- EXIT;
- break;
- }
- pg.flag = OBD_BRW_CREATE;
- CDEBUG(D_INFO, "Read page %ld ...\n", page->index);
-
- set->brw_callback = ll_brw_sync_wait;
- err = obd_brw(OBD_BRW_WRITE, dst_conn, &dstmd, 1, &pg, set);
- obd_brw_set_free(set);
-
- /* XXX should handle dst->o_size, dst->o_blocks here */
- if (err) {
- EXIT;
- break;
- }
-
- CDEBUG(D_INFO, "Wrote page %ld ...\n", page->index);
-
- index++;
- }
- dst->o_size = src->o_size;
- dst->o_blocks = src->o_blocks;
- dst->o_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
- unlock_page(page);
- __free_page(page);
-
- RETURN(err);
-}
-int filter_attach(struct obd_device *dev, obd_count len, void *data)
-{
- return lprocfs_reg_obd(dev, status_var_nm_1, dev);
-}
-
-int filter_detach(struct obd_device *dev)
-{
- return lprocfs_dereg_obd(dev);
-}
-static struct obd_ops filter_obd_ops = {
- o_attach: filter_attach,
- o_detach: filter_detach,
- o_get_info: filter_get_info,
- o_setup: filter_setup,
- o_cleanup: filter_cleanup,
- o_connect: filter_connect,
- o_disconnect: filter_disconnect,
- o_statfs: filter_statfs,
- o_getattr: filter_getattr,
- o_create: filter_create,
- o_setattr: filter_setattr,
- o_destroy: filter_destroy,
- o_open: filter_open,
- o_close: filter_close,
- o_brw: filter_pgcache_brw,
- o_punch: filter_truncate,
- o_preprw: filter_preprw,
- o_commitrw: filter_commitrw
-#if 0
- o_preallocate: filter_preallocate_inodes,
- o_migrate: filter_migrate,
- o_copy: filter_copy_data,
- o_iterate: filter_iterate
-#endif
-};
-
-
-static int __init obdfilter_init(void)
-{
- printk(KERN_INFO "Filtering OBD driver v0.001, info@clusterfs.com\n");
- filter_open_cache = kmem_cache_create("ll_filter_fdata",
- sizeof(struct filter_file_data),
- 0, 0, NULL, NULL);
- if (!filter_open_cache)
- RETURN(-ENOMEM);
-
- filter_dentry_cache = kmem_cache_create("ll_filter_dentry",
- sizeof(struct filter_dentry_data),
- 0, 0, NULL, NULL);
- if (!filter_dentry_cache) {
- kmem_cache_destroy(filter_open_cache);
- RETURN(-ENOMEM);
- }
-
- return class_register_type(&filter_obd_ops, status_class_var,
- OBD_FILTER_DEVICENAME);
-}
-
-static void __exit obdfilter_exit(void)
-{
- class_unregister_type(OBD_FILTER_DEVICENAME);
- if (kmem_cache_destroy(filter_dentry_cache))
- CERROR("couldn't free obdfilter dentry cache\n");
- if (kmem_cache_destroy(filter_open_cache))
- CERROR("couldn't free obdfilter open cache\n");
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Filtering OBD driver v1.0");
-MODULE_LICENSE("GPL");
-
-module_init(obdfilter_init);
-module_exit(obdfilter_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-
-int rd_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct obd_device* dev = (struct obd_device*)data;
- len += snprintf(page, count, "%s\n", dev->obd_uuid);
- return len;
-}
-int rd_blksize(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct statfs mystats;
- int len = 0;
-
- vfs_statfs(temp->u.filter.fo_sb, &mystats);
- len+=snprintf(page, count, "%ld\n", mystats.f_bsize);
- return len;
-}
-int rd_kbtotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct statfs mystats;
- int len = 0;
- __u32 blk_size;
- __u64 result;
-
- vfs_statfs(temp->u.filter.fo_sb, &mystats);
- blk_size = mystats.f_bsize;
- blk_size >>= 10;
- result = mystats.f_blocks;
- while(blk_size >>= 1){
- result <<= 1;
- }
- len+=snprintf(page, count, LPU64"\n", result);
- return len;
-}
-
-int rd_kbfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct statfs mystats;
- int len = 0;
- __u32 blk_size;
- __u64 result;
-
- vfs_statfs(temp->u.filter.fo_sb, &mystats);
- blk_size = mystats.f_bsize;
- blk_size >>= 10;
- result = mystats.f_bfree;
- while(blk_size >>= 1){
- result <<= 1;
- }
- len += snprintf(page, count, LPU64"\n", result);
- return len;
-}
-
-int rd_fstype(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- int len = 0;
- len += snprintf(page, count, "%s\n", temp->u.filter.fo_fstype);
- return len;
-}
-int rd_filestotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct statfs mystats;
- int len = 0;
- vfs_statfs(temp->u.filter.fo_sb, &mystats);
- len += snprintf(page, count, "%ld\n", mystats.f_files);
- return len;
-}
-
-int rd_filesfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct statfs mystats;
- int len = 0;
- vfs_statfs(temp->u.filter.fo_sb, &mystats);
- len += snprintf(page, count, "%ld\n", mystats.f_ffree);
- return len;
-}
-
-int rd_filegroups(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-struct lprocfs_vars status_var_nm_1[] = {
- {"status/uuid", rd_uuid, 0, 0},
- {"status/blocksize",rd_blksize, 0, 0},
- {"status/kbytestotal",rd_kbtotal, 0, 0},
- {"status/kbytesfree", rd_kbfree, 0, 0},
- {"status/filestotal", rd_filestotal, 0, 0},
- {"status/filesfree", rd_filesfree, 0, 0},
- {"status/filegroups", rd_filegroups, 0, 0},
- {"status/fstype", rd_fstype, 0, 0},
- {0}
-};
-int rd_numrefs(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_type* class = (struct obd_type*)data;
- int len = 0;
- len += snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-struct lprocfs_vars status_class_var[] = {
- {"status/num_refs", rd_numrefs, 0, 0},
- {0}
-};
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=
-
-MODULE = osc
-modulefs_DATA = osc.o
-EXTRA_PROGRAMS = osc
-
-LINX= obd_pack.c ll_pack.c client.c
-osc_SOURCES = osc_request.c lproc_osc.c $(LINX)
-
-obd_pack.c:
- test -e obd_pack.c || ln -sf $(top_srcdir)/lib/obd_pack.c
-ll_pack.c:
- test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c
-client.c:
- test -e client.c || ln -sf $(top_srcdir)/lib/client.c
-
-dist-hook:
- list='$(LINX)'; for f in $$list; do rm -f $(distdir)/$$f; done
-
-include $(top_srcdir)/Rules
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-int rd_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- struct obd_device* dev = (struct obd_device*)data;
- len += snprintf(page, count, "%s\n", dev->obd_uuid);
- return len;
-
-}
-int rd_blksize(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-int rd_kbytestotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_kbytesfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_filestotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_filesfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-int rd_filegroups(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-int rd_server_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
-
- struct obd_device* temp = (struct obd_device*)data;
- struct client_obd* cli = &temp->u.cli;
- int len = 0;
- len += snprintf(page, count, "%s\n",cli->cl_target_uuid);
- return len;
-
-
-}
-int rd_conn_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp=(struct obd_device*)data;
- struct client_obd* cli=&temp->u.cli;
- struct obd_import* imp=&cli->cl_import;
- int len = 0;
- len += snprintf(page, count, "%s\n",
- imp->imp_connection->c_remote_uuid);
- return len;
-
-}
-
-struct lprocfs_vars status_var_nm_1[] = {
- {"status/uuid", rd_uuid, 0, 0},
- {"status/blocksize",rd_blksize, 0, 0},
- {"status/kbytestotal", rd_kbytestotal, 0, 0},
- {"status/kbytesfree", rd_kbytesfree, 0, 0},
- {"status/filestotal", rd_filestotal, 0, 0},
- {"status/filesfree", rd_filesfree, 0, 0},
- {"status/filegroups", rd_filegroups, 0, 0},
- {"status/ost_server_uuid", rd_server_uuid, 0, 0},
- {"status/ost_conn_uuid", rd_conn_uuid, 0, 0},
- {0}
-};
-int rd_numrefs(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_type* class = (struct obd_type*)data;
- int len = 0;
- len += snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-struct lprocfs_vars status_class_var[] = {
- {"status/num_refs", rd_numrefs, 0, 0},
- {0}
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- * Author Peter Braam <braam@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * For testing and management it is treated as an obd_device,
- * although * it does not export a full OBD method table (the
- * requests are coming * in over the wire, so object target modules
- * do not have a full * method table.)
- *
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_OSC
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/lustre_dlm.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
-#include <linux/workqueue.h>
-#endif
-#include <linux/kp30.h>
-#include <linux/lustre_mds.h> /* for mds_objid */
-#include <linux/obd_ost.h>
-#include <linux/obd_lov.h> /* for IOC_LOV_SET_OSC_ACTIVE */
-#include <linux/ctype.h>
-#include <linux/init.h>
-#include <linux/lustre_ha.h>
-#include <linux/obd_support.h> /* for OBD_FAIL_CHECK */
-#include <linux/lustre_lite.h> /* for ll_i2info */
-#include <portals/lib-types.h> /* for PTL_MD_MAX_IOV */
-#include <linux/lprocfs_status.h>
-
-extern struct lprocfs_vars status_var_nm_1[];
-extern struct lprocfs_vars status_class_var[];
-
-static int osc_attach(struct obd_device *dev, obd_count len, void *data)
-{
- return lprocfs_reg_obd(dev, status_var_nm_1, dev);
-}
-
-static int osc_detach(struct obd_device *dev)
-{
- return lprocfs_dereg_obd(dev);
-}
-
-/* Pack OSC object metadata for shipment to the MDS. */
-static int osc_packmd(struct lustre_handle *conn, struct lov_mds_md **lmmp,
- struct lov_stripe_md *lsm)
-{
- int lmm_size;
-
- lmm_size = sizeof(**lmmp);
- if (!lmmp)
- RETURN(lmm_size);
-
- if (*lmmp && !lsm) {
- OBD_FREE(*lmmp, lmm_size);
- *lmmp = NULL;
- RETURN(0);
- }
-
- if (!*lmmp) {
- OBD_ALLOC(*lmmp, lmm_size);
- if (!*lmmp)
- RETURN(-ENOMEM);
- }
- if (lsm) {
- LASSERT(lsm->lsm_object_id);
- (*lmmp)->lmm_object_id = (lsm->lsm_object_id);
- }
-
- return lmm_size;
-}
-
-static int osc_unpackmd(struct lustre_handle *conn, struct lov_stripe_md **lsmp,
- struct lov_mds_md *lmm)
-{
- int lsm_size;
-
- lsm_size = sizeof(**lsmp);
- if (!lsmp)
- RETURN(lsm_size);
-
- if (*lsmp && !lmm) {
- OBD_FREE(*lsmp, lsm_size);
- *lsmp = NULL;
- RETURN(0);
- }
-
- if (!*lsmp) {
- OBD_ALLOC(*lsmp, lsm_size);
- if (!*lsmp)
- RETURN(-ENOMEM);
- }
-
- /* XXX endianness */
- if (lmm) {
- (*lsmp)->lsm_object_id = (lmm->lmm_object_id);
- LASSERT((*lsmp)->lsm_object_id);
- }
-
- return lsm_size;
-}
-
-static int osc_getattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- struct ptlrpc_request *request;
- struct ost_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- request = ptlrpc_prep_req(class_conn2cliimp(conn), OST_GETATTR, 1,
- &size, NULL);
- if (!request)
- RETURN(-ENOMEM);
-
- body = lustre_msg_buf(request->rq_reqmsg, 0);
-#warning FIXME: pack only valid fields instead of memcpy, endianness
- memcpy(&body->oa, oa, sizeof(*oa));
-
- request->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(request);
- if (rc) {
- CERROR("%s failed: rc = %d\n", __FUNCTION__, rc);
- GOTO(out, rc);
- }
-
- body = lustre_msg_buf(request->rq_repmsg, 0);
- CDEBUG(D_INODE, "mode: %o\n", body->oa.o_mode);
- if (oa)
- memcpy(oa, &body->oa, sizeof(*oa));
-
- EXIT;
- out:
- ptlrpc_req_finished(request);
- return rc;
-}
-
-static int osc_open(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- struct ptlrpc_request *request;
- struct ost_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- request = ptlrpc_prep_req(class_conn2cliimp(conn), OST_OPEN, 1, &size,
- NULL);
- if (!request)
- RETURN(-ENOMEM);
-
- body = lustre_msg_buf(request->rq_reqmsg, 0);
-#warning FIXME: pack only valid fields instead of memcpy, endianness
- memcpy(&body->oa, oa, sizeof(*oa));
-
- request->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(request);
- if (rc)
- GOTO(out, rc);
-
- body = lustre_msg_buf(request->rq_repmsg, 0);
- CDEBUG(D_INODE, "mode: %o\n", body->oa.o_mode);
- if (oa)
- memcpy(oa, &body->oa, sizeof(*oa));
-
- EXIT;
- out:
- ptlrpc_req_finished(request);
- return rc;
-}
-
-static int osc_close(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- struct ptlrpc_request *request;
- struct ost_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- request = ptlrpc_prep_req(class_conn2cliimp(conn), OST_CLOSE, 1, &size,
- NULL);
- if (!request)
- RETURN(-ENOMEM);
-
- body = lustre_msg_buf(request->rq_reqmsg, 0);
-#warning FIXME: pack only valid fields instead of memcpy, endianness
- memcpy(&body->oa, oa, sizeof(*oa));
-
- request->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(request);
- if (rc)
- GOTO(out, rc);
-
- body = lustre_msg_buf(request->rq_repmsg, 0);
- CDEBUG(D_INODE, "mode: %o\n", body->oa.o_mode);
- if (oa)
- memcpy(oa, &body->oa, sizeof(*oa));
-
- EXIT;
- out:
- ptlrpc_req_finished(request);
- return rc;
-}
-
-static int osc_setattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- struct ptlrpc_request *request;
- struct ost_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- request = ptlrpc_prep_req(class_conn2cliimp(conn), OST_SETATTR, 1,
- &size, NULL);
- if (!request)
- RETURN(-ENOMEM);
-
- body = lustre_msg_buf(request->rq_reqmsg, 0);
- memcpy(&body->oa, oa, sizeof(*oa));
-
- request->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(request);
-
- ptlrpc_req_finished(request);
- return rc;
-}
-
-static int osc_create(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md **ea)
-{
- struct ptlrpc_request *request;
- struct ost_body *body;
- struct lov_stripe_md *lsm;
- int rc, size = sizeof(*body);
- ENTRY;
-
- LASSERT(oa);
- LASSERT(ea);
-
- lsm = *ea;
- if (!lsm) {
- rc = obd_alloc_memmd(conn, &lsm);
- if (rc < 0)
- RETURN(rc);
- }
-
- request = ptlrpc_prep_req(class_conn2cliimp(conn), OST_CREATE, 1, &size,
- NULL);
- if (!request)
- GOTO(out, rc = -ENOMEM);
-
- body = lustre_msg_buf(request->rq_reqmsg, 0);
- memcpy(&body->oa, oa, sizeof(*oa));
-
- request->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(request);
- if (rc)
- GOTO(out_req, rc);
-
- body = lustre_msg_buf(request->rq_repmsg, 0);
- memcpy(oa, &body->oa, sizeof(*oa));
-
- lsm->lsm_object_id = oa->o_id;
- lsm->lsm_stripe_count = 0;
- *ea = lsm;
- EXIT;
-out_req:
- ptlrpc_req_finished(request);
-out:
- if (rc && !*ea)
- obd_free_memmd(conn, &lsm);
- return rc;
-}
-
-static int osc_punch(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md, obd_size start,
- obd_size end)
-{
- struct ptlrpc_request *request;
- struct ost_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- if (!oa) {
- CERROR("oa NULL\n");
- RETURN(-EINVAL);
- }
-
- request = ptlrpc_prep_req(class_conn2cliimp(conn), OST_PUNCH, 1, &size,
- NULL);
- if (!request)
- RETURN(-ENOMEM);
-
- body = lustre_msg_buf(request->rq_reqmsg, 0);
-#warning FIXME: pack only valid fields instead of memcpy, endianness, valid
- memcpy(&body->oa, oa, sizeof(*oa));
-
- /* overload the size and blocks fields in the oa with start/end */
- body->oa.o_size = HTON__u64(start);
- body->oa.o_blocks = HTON__u64(end);
- body->oa.o_valid |= HTON__u32(OBD_MD_FLSIZE | OBD_MD_FLBLOCKS);
-
- request->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(request);
- if (rc)
- GOTO(out, rc);
-
- body = lustre_msg_buf(request->rq_repmsg, 0);
- memcpy(oa, &body->oa, sizeof(*oa));
-
- EXIT;
- out:
- ptlrpc_req_finished(request);
- return rc;
-}
-
-static int osc_destroy(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea)
-{
- struct ptlrpc_request *request;
- struct ost_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- if (!oa) {
- CERROR("oa NULL\n");
- RETURN(-EINVAL);
- }
- request = ptlrpc_prep_req(class_conn2cliimp(conn), OST_DESTROY, 1,
- &size, NULL);
- if (!request)
- RETURN(-ENOMEM);
-
- body = lustre_msg_buf(request->rq_reqmsg, 0);
-#warning FIXME: pack only valid fields instead of memcpy, endianness
- memcpy(&body->oa, oa, sizeof(*oa));
-
- request->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(request);
- if (rc)
- GOTO(out, rc);
-
- body = lustre_msg_buf(request->rq_repmsg, 0);
- memcpy(oa, &body->oa, sizeof(*oa));
-
- EXIT;
- out:
- ptlrpc_req_finished(request);
- return rc;
-}
-
-/* Our bulk-unmapping bottom half. */
-static void unmap_and_decref_bulk_desc(void *data)
-{
- struct ptlrpc_bulk_desc *desc = data;
- struct list_head *tmp;
- ENTRY;
-
- /* This feels wrong to me. */
- list_for_each(tmp, &desc->bd_page_list) {
- struct ptlrpc_bulk_page *bulk;
- bulk = list_entry(tmp, struct ptlrpc_bulk_page, bp_link);
-
- kunmap(bulk->bp_page);
- obd_kmap_put(1);
- }
-
- ptlrpc_bulk_decref(desc);
- EXIT;
-}
-
-/* this is the callback function which is invoked by the Portals
- * event handler associated with the bulk_sink queue and bulk_source queue.
- */
-static void osc_ptl_ev_hdlr(struct ptlrpc_bulk_desc *desc)
-{
- ENTRY;
-
- LASSERT(desc->bd_brw_set != NULL);
- LASSERT(desc->bd_brw_set->brw_callback != NULL);
-
- desc->bd_brw_set->brw_callback(desc->bd_brw_set, CB_PHASE_FINISH);
-
- /* We can't kunmap the desc from interrupt context, so we do it from
- * the bottom half above. */
- prepare_work(&desc->bd_queue, unmap_and_decref_bulk_desc, desc);
- schedule_work(&desc->bd_queue);
-
- EXIT;
-}
-
-static int osc_brw_read(struct lustre_handle *conn, struct lov_stripe_md *lsm,
- obd_count page_count, struct brw_page *pga,
- struct obd_brw_set *set)
-{
- struct obd_import *imp = class_conn2cliimp(conn);
- struct ptlrpc_connection *connection = imp->imp_connection;
- struct ptlrpc_request *request = NULL;
- struct ptlrpc_bulk_desc *desc = NULL;
- struct ost_body *body;
- int rc, size[3] = {sizeof(*body)}, mapped = 0;
- void *iooptr, *nioptr;
- __u32 xid;
- ENTRY;
-
- size[1] = sizeof(struct obd_ioobj);
- size[2] = page_count * sizeof(struct niobuf_remote);
-
- request = ptlrpc_prep_req(imp, OST_READ, 3, size, NULL);
- if (!request)
- RETURN(-ENOMEM);
-
- body = lustre_msg_buf(request->rq_reqmsg, 0);
-
- desc = ptlrpc_prep_bulk(connection);
- if (!desc)
- GOTO(out_req, rc = -ENOMEM);
- desc->bd_portal = OST_BULK_PORTAL;
- desc->bd_ptl_ev_hdlr = osc_ptl_ev_hdlr;
- CDEBUG(D_PAGE, "desc = %p\n", desc);
-
- iooptr = lustre_msg_buf(request->rq_reqmsg, 1);
- nioptr = lustre_msg_buf(request->rq_reqmsg, 2);
- ost_pack_ioo(&iooptr, lsm, page_count);
- /* end almost identical to brw_write case */
-
- spin_lock(&imp->imp_lock);
- xid = ++imp->imp_last_xid; /* single xid for all pages */
- spin_unlock(&imp->imp_lock);
-
- obd_kmap_get(page_count, 0);
-
- for (mapped = 0; mapped < page_count; mapped++) {
- struct ptlrpc_bulk_page *bulk = ptlrpc_prep_bulk_page(desc);
- if (bulk == NULL)
- GOTO(out_unmap, rc = -ENOMEM);
-
- bulk->bp_xid = xid; /* single xid for all pages */
-
- bulk->bp_buf = kmap(pga[mapped].pg);
- bulk->bp_page = pga[mapped].pg;
- bulk->bp_buflen = PAGE_SIZE;
- ost_pack_niobuf(&nioptr, pga[mapped].off, pga[mapped].count,
- pga[mapped].flag, bulk->bp_xid);
- }
-
- /*
- * Register the bulk first, because the reply could arrive out of order,
- * and we want to be ready for the bulk data.
- *
- * One reference is released when brw_finish is complete, the other when
- * the caller removes us from the "set" list.
- *
- * On error, we never do the brw_finish, so we handle all decrefs.
- */
- if (OBD_FAIL_CHECK(OBD_FAIL_OSC_BRW_READ_BULK)) {
- CERROR("obd_fail_loc=%x, skipping register_bulk\n",
- OBD_FAIL_OSC_BRW_READ_BULK);
- } else {
- rc = ptlrpc_register_bulk(desc);
- if (rc)
- GOTO(out_unmap, rc);
- obd_brw_set_add(set, desc);
- }
-
- request->rq_replen = lustre_msg_size(1, size);
- rc = ptlrpc_queue_wait(request);
-
- /*
- * XXX: If there is an error during the processing of the callback,
- * such as a timeout in a sleep that it performs, brw_finish
- * will never get called, and we'll leak the desc, fail to kunmap
- * things, cats will live with dogs. One solution would be to
- * export brw_finish as osc_brw_finish, so that the timeout case
- * and its kin could call it for proper cleanup. An alternative
- * would be for an error return from the callback to cause us to
- * clean up, but that doesn't help the truly async cases (like
- * LOV), which will immediately return from their PHASE_START
- * callback, before any such cleanup-requiring error condition can
- * be detected.
- */
- out_req:
- ptlrpc_req_finished(request);
- RETURN(rc);
-
- /* Clean up on error. */
-out_unmap:
- while (mapped-- > 0)
- kunmap(pga[mapped].pg);
- obd_kmap_put(page_count);
- ptlrpc_bulk_decref(desc);
- goto out_req;
-}
-
-static int osc_brw_write(struct lustre_handle *conn, struct lov_stripe_md *md,
- obd_count page_count, struct brw_page *pga,
- struct obd_brw_set *set)
-{
- struct ptlrpc_connection *connection =
- client_conn2cli(conn)->cl_import.imp_connection;
- struct ptlrpc_request *request = NULL;
- struct ptlrpc_bulk_desc *desc = NULL;
- struct ost_body *body;
- struct niobuf_local *local = NULL;
- struct niobuf_remote *remote;
- int rc, j, size[3] = {sizeof(*body)}, mapped = 0;
- void *iooptr, *nioptr;
- ENTRY;
-
- size[1] = sizeof(struct obd_ioobj);
- size[2] = page_count * sizeof(*remote);
-
- request = ptlrpc_prep_req(class_conn2cliimp(conn), OST_WRITE, 3, size,
- NULL);
- if (!request)
- RETURN(-ENOMEM);
-
- body = lustre_msg_buf(request->rq_reqmsg, 0);
-
- desc = ptlrpc_prep_bulk(connection);
- if (!desc)
- GOTO(out_req, rc = -ENOMEM);
- desc->bd_portal = OSC_BULK_PORTAL;
- desc->bd_ptl_ev_hdlr = osc_ptl_ev_hdlr;
- CDEBUG(D_PAGE, "desc = %p\n", desc);
-
- iooptr = lustre_msg_buf(request->rq_reqmsg, 1);
- nioptr = lustre_msg_buf(request->rq_reqmsg, 2);
- ost_pack_ioo(&iooptr, md, page_count);
- /* end almost identical to brw_read case */
-
- OBD_ALLOC(local, page_count * sizeof(*local));
- if (!local)
- GOTO(out_desc, rc = -ENOMEM);
-
- obd_kmap_get(page_count, 0);
-
- for (mapped = 0; mapped < page_count; mapped++) {
- local[mapped].addr = kmap(pga[mapped].pg);
-
- CDEBUG(D_INFO, "kmap(pg) = %p ; pg->flags = %lx ; pg->count = "
- "%d ; page %d of %d\n",
- local[mapped].addr, pga[mapped].pg->flags,
- page_count(pga[mapped].pg),
- mapped, page_count - 1);
-
- local[mapped].offset = pga[mapped].off;
- local[mapped].len = pga[mapped].count;
- ost_pack_niobuf(&nioptr, pga[mapped].off, pga[mapped].count,
- pga[mapped].flag, 0);
- }
-
- size[1] = page_count * sizeof(*remote);
- request->rq_replen = lustre_msg_size(2, size);
- rc = ptlrpc_queue_wait(request);
- if (rc)
- GOTO(out_unmap, rc);
-
- nioptr = lustre_msg_buf(request->rq_repmsg, 1);
- if (!nioptr)
- GOTO(out_unmap, rc = -EINVAL);
-
- if (request->rq_repmsg->buflens[1] != size[1]) {
- CERROR("buffer length wrong (%d vs. %d)\n",
- request->rq_repmsg->buflens[1], size[1]);
- GOTO(out_unmap, rc = -EINVAL);
- }
-
- for (j = 0; j < page_count; j++) {
- struct ptlrpc_bulk_page *bulk;
-
- ost_unpack_niobuf(&nioptr, &remote);
-
- bulk = ptlrpc_prep_bulk_page(desc);
- if (!bulk)
- GOTO(out_unmap, rc = -ENOMEM);
-
- bulk->bp_buf = (void *)(unsigned long)local[j].addr;
- bulk->bp_buflen = local[j].len;
- bulk->bp_xid = remote->xid;
- bulk->bp_page = pga[j].pg;
- }
-
- if (desc->bd_page_count != page_count)
- LBUG();
-
- if (OBD_FAIL_CHECK(OBD_FAIL_OSC_BRW_WRITE_BULK))
- GOTO(out_unmap, rc = 0);
-
- OBD_FREE(local, page_count * sizeof(*local));
-
- /* One reference is released when brw_finish is complete, the other
- * when the caller removes it from the "set" list. */
- obd_brw_set_add(set, desc);
- rc = ptlrpc_send_bulk(desc);
-
- /* XXX: Mike, same question as in osc_brw_read. */
-out_req:
- ptlrpc_req_finished(request);
- RETURN(rc);
-
- /* Clean up on error. */
-out_unmap:
- while (mapped-- > 0)
- kunmap(pga[mapped].pg);
-
- obd_kmap_put(page_count);
-
- OBD_FREE(local, page_count * sizeof(*local));
-out_desc:
- ptlrpc_bulk_decref(desc);
- goto out_req;
-}
-
-static int osc_brw(int cmd, struct lustre_handle *conn,
- struct lov_stripe_md *md, obd_count page_count,
- struct brw_page *pga, struct obd_brw_set *set)
-{
- ENTRY;
-
- while (page_count) {
- obd_count pages_per_brw;
- int rc;
-
- if (page_count > PTL_MD_MAX_IOV)
- pages_per_brw = PTL_MD_MAX_IOV;
- else
- pages_per_brw = page_count;
-
- if (cmd & OBD_BRW_WRITE)
- rc = osc_brw_write(conn, md, pages_per_brw, pga, set);
- else
- rc = osc_brw_read(conn, md, pages_per_brw, pga, set);
-
- if (rc != 0)
- RETURN(rc);
-
- page_count -= pages_per_brw;
- pga += pages_per_brw;
- }
- RETURN(0);
-}
-
-static int osc_enqueue(struct lustre_handle *connh, struct lov_stripe_md *lsm,
- struct lustre_handle *parent_lock,
- __u32 type, void *extentp, int extent_len, __u32 mode,
- int *flags, void *callback, void *data, int datalen,
- struct lustre_handle *lockh)
-{
- __u64 res_id[RES_NAME_SIZE] = { lsm->lsm_object_id };
- struct obd_device *obddev = class_conn2obd(connh);
- struct ldlm_extent *extent = extentp;
- int rc;
- ENTRY;
-
- /* Filesystem locks are given a bit of special treatment: if
- * this is not a file size lock (which has end == -1), we
- * fixup the lock to start and end on page boundaries. */
- if (extent->end != OBD_OBJECT_EOF) {
- extent->start &= PAGE_MASK;
- extent->end = (extent->end & PAGE_MASK) + PAGE_SIZE - 1;
- }
-
- /* Next, search for already existing extent locks that will cover us */
- rc = ldlm_lock_match(obddev->obd_namespace, res_id, type, extent,
- sizeof(extent), mode, lockh);
- if (rc == 1)
- /* We already have a lock, and it's referenced */
- RETURN(ELDLM_OK);
-
- /* If we're trying to read, we also search for an existing PW lock. The
- * VFS and page cache already protect us locally, so lots of readers/
- * writers can share a single PW lock.
- *
- * There are problems with conversion deadlocks, so instead of
- * converting a read lock to a write lock, we'll just enqueue a new
- * one.
- *
- * At some point we should cancel the read lock instead of making them
- * send us a blocking callback, but there are problems with canceling
- * locks out from other users right now, too. */
-
- if (mode == LCK_PR) {
- rc = ldlm_lock_match(obddev->obd_namespace, res_id, type,
- extent, sizeof(extent), LCK_PW, lockh);
- if (rc == 1) {
- /* FIXME: This is not incredibly elegant, but it might
- * be more elegant than adding another parameter to
- * lock_match. I want a second opinion. */
- ldlm_lock_addref(lockh, LCK_PR);
- ldlm_lock_decref(lockh, LCK_PW);
-
- RETURN(ELDLM_OK);
- }
- }
-
- rc = ldlm_cli_enqueue(connh, NULL, obddev->obd_namespace, parent_lock,
- res_id, type, extent, sizeof(extent), mode, flags,
- ldlm_completion_ast, callback, data, datalen,
- lockh);
- RETURN(rc);
-}
-
-static int osc_cancel(struct lustre_handle *oconn, struct lov_stripe_md *md,
- __u32 mode, struct lustre_handle *lockh)
-{
- ENTRY;
-
- ldlm_lock_decref(lockh, mode);
-
- RETURN(0);
-}
-
-static int osc_cancel_unused(struct lustre_handle *connh,
- struct lov_stripe_md *lsm, int flags)
-{
- struct obd_device *obddev = class_conn2obd(connh);
- __u64 res_id[RES_NAME_SIZE] = { lsm->lsm_object_id };
-
- return ldlm_cli_cancel_unused(obddev->obd_namespace, res_id, flags);
-}
-
-static int osc_statfs(struct lustre_handle *conn, struct obd_statfs *osfs)
-{
- struct ptlrpc_request *request;
- int rc, size = sizeof(*osfs);
- ENTRY;
-
- request = ptlrpc_prep_req(class_conn2cliimp(conn), OST_STATFS, 0, NULL,
- NULL);
- if (!request)
- RETURN(-ENOMEM);
-
- request->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(request);
- if (rc) {
- CERROR("%s failed: rc = %d\n", __FUNCTION__, rc);
- GOTO(out, rc);
- }
-
- obd_statfs_unpack(osfs, lustre_msg_buf(request->rq_repmsg, 0));
-
- EXIT;
- out:
- ptlrpc_req_finished(request);
- return rc;
-}
-
-static int osc_iocontrol(unsigned int cmd, struct lustre_handle *conn, int len,
- void *karg, void *uarg)
-{
- struct obd_device *obddev = class_conn2obd(conn);
- struct obd_ioctl_data *data = karg;
- int err = 0;
- ENTRY;
-
- switch (cmd) {
- case IOC_LDLM_TEST: {
- err = ldlm_test(obddev, conn);
- CERROR("-- done err %d\n", err);
- GOTO(out, err);
- }
- case IOC_LDLM_REGRESS_START: {
- unsigned int numthreads = 1;
- unsigned int numheld = 10;
- unsigned int numres = 10;
- unsigned int numext = 10;
- char *parse;
-
- if (data->ioc_inllen1) {
- parse = data->ioc_inlbuf1;
- if (*parse != '\0') {
- while(isspace(*parse)) parse++;
- numthreads = simple_strtoul(parse, &parse, 0);
- while(isspace(*parse)) parse++;
- }
- if (*parse != '\0') {
- while(isspace(*parse)) parse++;
- numheld = simple_strtoul(parse, &parse, 0);
- while(isspace(*parse)) parse++;
- }
- if (*parse != '\0') {
- while(isspace(*parse)) parse++;
- numres = simple_strtoul(parse, &parse, 0);
- while(isspace(*parse)) parse++;
- }
- if (*parse != '\0') {
- while(isspace(*parse)) parse++;
- numext = simple_strtoul(parse, &parse, 0);
- while(isspace(*parse)) parse++;
- }
- }
-
- err = ldlm_regression_start(obddev, conn, numthreads,
- numheld, numres, numext);
-
- CERROR("-- done err %d\n", err);
- GOTO(out, err);
- }
- case IOC_LDLM_REGRESS_STOP: {
- err = ldlm_regression_stop();
- CERROR("-- done err %d\n", err);
- GOTO(out, err);
- }
- case IOC_OSC_REGISTER_LOV: {
- if (obddev->u.cli.cl_containing_lov)
- GOTO(out, err = -EALREADY);
- obddev->u.cli.cl_containing_lov = (struct obd_device *)karg;
- GOTO(out, err);
- }
- case OBD_IOC_LOV_GET_CONFIG: {
- char *buf;
- struct lov_desc *desc;
- obd_uuid_t *uuidp;
-
- buf = NULL;
- len = 0;
- if (obd_ioctl_getdata(&buf, &len, (void *)uarg))
- GOTO(out, err = -EINVAL);
-
- data = (struct obd_ioctl_data *)buf;
-
- if (sizeof(*desc) > data->ioc_inllen1) {
- OBD_FREE(buf, len);
- GOTO(out, err = -EINVAL);
- }
-
- if (data->ioc_inllen2 < sizeof(*uuidp)) {
- OBD_FREE(buf, len);
- GOTO(out, err = -EINVAL);
- }
-
- desc = (struct lov_desc *)data->ioc_inlbuf1;
- desc->ld_tgt_count = 1;
- desc->ld_active_tgt_count = 1;
- desc->ld_default_stripe_count = 1;
- desc->ld_default_stripe_size = 0;
- desc->ld_default_stripe_offset = 0;
- desc->ld_pattern = 0;
- memcpy(desc->ld_uuid, obddev->obd_uuid, sizeof(*uuidp));
-
- uuidp = (obd_uuid_t *)data->ioc_inlbuf2;
- memcpy(uuidp, obddev->obd_uuid, sizeof(*uuidp));
-
- err = copy_to_user((void *)uarg, buf, len);
- if (err)
- err = -EFAULT;
- OBD_FREE(buf, len);
- GOTO(out, err);
- }
- default:
- CERROR ("osc_ioctl(): unrecognised ioctl %#lx\n", cmd);
- GOTO(out, err = -ENOTTY);
- }
-out:
- return err;
-}
-
-static void set_osc_active(struct obd_import *imp, int active)
-{
- struct obd_device *notify_obd = imp->imp_obd->u.cli.cl_containing_lov;
-
- if (notify_obd == NULL)
- return;
-
- /* How gross is _this_? */
- if (!list_empty(¬ify_obd->obd_exports)) {
- int rc;
- struct lustre_handle fakeconn;
- struct obd_ioctl_data ioc_data;
- struct obd_export *exp =
- list_entry(notify_obd->obd_exports.next,
- struct obd_export, exp_obd_chain);
-
- fakeconn.addr = (__u64)(unsigned long)exp;
- fakeconn.cookie = exp->exp_cookie;
- ioc_data.ioc_inlbuf1 = imp->imp_obd->obd_uuid;
- ioc_data.ioc_offset = active;
- rc = obd_iocontrol(IOC_LOV_SET_OSC_ACTIVE, &fakeconn,
- sizeof ioc_data, &ioc_data, NULL);
- if (rc)
- CERROR("disabling %s on LOV %p/%s: %d\n",
- imp->imp_obd->obd_uuid, notify_obd,
- notify_obd->obd_uuid, rc);
- } else {
- CDEBUG(D_HA, "No exports for obd %p/%s, can't notify about "
- "%p\n", notify_obd, notify_obd->obd_uuid,
- imp->imp_obd->obd_uuid);
- }
-}
-
-
-/* XXX looks a lot like super.c:invalidate_request_list, don't it? */
-static void abort_inflight_for_import(struct obd_import *imp)
-{
- struct list_head *tmp, *n;
-
- /* Make sure that no new requests get processed for this import.
- * ptlrpc_queue_wait must (and does) hold imp_lock while testing this
- * flag and then putting requests on sending_list or delayed_list.
- */
- spin_lock(&imp->imp_lock);
- imp->imp_flags |= IMP_INVALID;
- spin_unlock(&imp->imp_lock);
-
- list_for_each_safe(tmp, n, &imp->imp_sending_list) {
- struct ptlrpc_request *req =
- list_entry(tmp, struct ptlrpc_request, rq_list);
-
- DEBUG_REQ(D_HA, req, "inflight");
- req->rq_flags |= PTL_RPC_FL_ERR;
- wake_up(&req->rq_wait_for_rep);
- }
-
- list_for_each_safe(tmp, n, &imp->imp_delayed_list) {
- struct ptlrpc_request *req =
- list_entry(tmp, struct ptlrpc_request, rq_list);
-
- DEBUG_REQ(D_HA, req, "aborting waiting req");
- req->rq_flags |= PTL_RPC_FL_ERR;
- wake_up(&req->rq_wait_for_rep);
- }
-}
-
-static int osc_recover(struct obd_import *imp, int phase)
-{
- int rc;
- ENTRY;
-
- switch(phase) {
- case PTLRPC_RECOVD_PHASE_PREPARE: {
- struct ldlm_namespace *ns = imp->imp_obd->obd_namespace;
- ldlm_namespace_cleanup(ns, 1 /* no network ops */);
- abort_inflight_for_import(imp);
- set_osc_active(imp, 0 /* inactive */);
- RETURN(0);
- }
- case PTLRPC_RECOVD_PHASE_RECOVER:
- imp->imp_flags &= ~IMP_INVALID;
- rc = ptlrpc_reconnect_import(imp, OST_CONNECT);
- if (rc) {
- imp->imp_flags |= IMP_INVALID;
- RETURN(rc);
- }
- set_osc_active(imp, 1 /* active */);
- RETURN(0);
- default:
- RETURN(-EINVAL);
- }
-}
-
-static int osc_connect(struct lustre_handle *conn, struct obd_device *obd,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- struct obd_import *imp = &obd->u.cli.cl_import;
- imp->imp_recover = osc_recover;
- return client_obd_connect(conn, obd, cluuid, recovd, recover);
-}
-
-struct obd_ops osc_obd_ops = {
- o_attach: osc_attach,
- o_detach: osc_detach,
- o_setup: client_obd_setup,
- o_cleanup: client_obd_cleanup,
- o_connect: osc_connect,
- o_disconnect: client_obd_disconnect,
- o_statfs: osc_statfs,
- o_packmd: osc_packmd,
- o_unpackmd: osc_unpackmd,
- o_create: osc_create,
- o_destroy: osc_destroy,
- o_getattr: osc_getattr,
- o_setattr: osc_setattr,
- o_open: osc_open,
- o_close: osc_close,
- o_brw: osc_brw,
- o_punch: osc_punch,
- o_enqueue: osc_enqueue,
- o_cancel: osc_cancel,
- o_cancel_unused: osc_cancel_unused,
- o_iocontrol: osc_iocontrol
-};
-
-static int __init osc_init(void)
-{
- RETURN(class_register_type(&osc_obd_ops, status_class_var,
- LUSTRE_OSC_NAME));
-}
-
-static void __exit osc_exit(void)
-{
- class_unregister_type(LUSTRE_OSC_NAME);
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Object Storage Client (OSC) v1.0");
-MODULE_LICENSE("GPL");
-
-module_init(osc_init);
-module_exit(osc_exit);
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=
-MODULE = ost
-modulefs_DATA = ost.o
-EXTRA_PROGRAMS = ost
-
-LINX=obd_pack.c ll_pack.c target.c
-
-ll_pack.c:
- test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c
-obd_pack.c:
- test -e obd_pack.c || ln -sf $(top_srcdir)/lib/obd_pack.c
-target.c:
- test -e target.c || ln -sf $(top_srcdir)/lib/target.c
-
-ost_SOURCES = ost_handler.c lproc_ost.c $(LINX)
-dist-hook:
- list='$(LINX)'; for f in $$list; do rm -f $(distdir)/$$f; done
-
-include $(top_srcdir)/Rules
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_OST
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-
-int rd_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
-
- struct obd_device* temp = (struct obd_device*)data;
- int len = 0;
- len += snprintf(page, count, "%s\n", temp->obd_uuid);
- return len;
-
-
-}
-int rd_blksize(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
-
- struct obd_device* temp = (struct obd_device*)data;
- struct ost_obd *ost = &temp->u.ost;
- struct lustre_handle *conn = &ost->ost_conn;
- struct obd_statfs mystats;
- int len = 0;
-
- obd_statfs(conn, &mystats);
- len += snprintf(page, count, "%d\n", mystats.os_bsize);
- return len;
-
-}
-int rd_kbtotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct ost_obd *ost = &temp->u.ost;
- struct lustre_handle *conn = &ost->ost_conn;
- struct obd_statfs mystats;
- int len = 0;
- __u32 blk_size;
- __u64 result;
-
- obd_statfs(conn, &mystats);
- blk_size = mystats.os_bsize;
- blk_size >>= 10;
- result = mystats.os_blocks;
- while(blk_size >>= 1){
- result <<= 1;
- }
- len += snprintf(page, count, LPU64"\n", result);
- return len;
-
-}
-
-
-int rd_kbfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
-
- struct obd_device* temp = (struct obd_device*)data;
- struct ost_obd *ost = &temp->u.ost;
- struct lustre_handle *conn = &ost->ost_conn;
- struct obd_statfs mystats;
- int len = 0;
- __u32 blk_size;
- __u64 result;
-
- obd_statfs(conn, &mystats);
- blk_size = mystats.os_bsize;
- blk_size >>= 10;
- result = mystats.os_bfree;
- while(blk_size >>= 1){
- result <<= 1;
- }
- len += snprintf(page, count, LPU64"\n", result);
- return len;
-}
-
-int rd_filestotal(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_device* temp = (struct obd_device*)data;
- struct ost_obd *ost = &temp->u.ost;
- struct lustre_handle *conn = &ost->ost_conn;
- struct obd_statfs mystats;
- int len = 0;
-
- obd_statfs(conn, &mystats);
- len += snprintf(page, count, LPU64"\n",mystats.os_files);
- return len;
-
-}
-
-int rd_filesfree(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
-
- struct obd_device* temp = (struct obd_device*)data;
- struct ost_obd *ost = &temp->u.ost;
- struct lustre_handle *conn = &ost->ost_conn;
- struct obd_statfs mystats;
- int len = 0;
-
- obd_statfs(conn, &mystats);
- len += snprintf(page, count, LPU64"\n", mystats.os_ffree);
- return len;
-
-}
-
-int rd_filegroups(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- return 0;
-}
-
-struct lprocfs_vars status_var_nm_1[] = {
- {"status/uuid", rd_uuid, 0, 0},
- {"status/blocksize",rd_blksize, 0, 0},
- {"status/kbytesfree", rd_kbfree, 0, 0},
- {"status/kbytestotal", rd_kbtotal, 0, 0},
- {"status/filestotal", rd_filestotal, 0, 0},
- {"status/filesfree", rd_filesfree, 0, 0},
- {"status/filegroups", rd_filegroups, 0, 0},
- {0}
-};
-
-int rd_numrefs(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_type* class = (struct obd_type*)data;
- int len = 0;
- len += snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-struct lprocfs_vars status_class_var[] = {
- {"status/num_refs", rd_numrefs, 0, 0},
- {0}
-};
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- * Author: Peter J. Braam <braam@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Storage Target Handling functions
- * Lustre Object Server Module (OST)
- *
- * This server is single threaded at present (but can easily be multi
- * threaded). For testing and management it is treated as an
- * obd_device, although it does not export a full OBD method table
- * (the requests are coming in over the wire, so object target
- * modules do not have a full method table.)
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_OST
-
-#include <linux/module.h>
-#include <linux/obd_ost.h>
-#include <linux/lustre_net.h>
-#include <linux/lustre_dlm.h>
-#include <linux/init.h>
-#include <linux/lprocfs_status.h>
-
-extern struct lprocfs_vars status_var_nm_1[];
-extern struct lprocfs_vars status_class_var[];
-
-static int ost_destroy(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- struct ost_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
-
- req->rq_status = obd_destroy(conn, &body->oa, NULL);
- RETURN(0);
-}
-
-static int ost_getattr(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- struct ost_body *body, *repbody;
- int rc, size = sizeof(*body);
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
-
- repbody = lustre_msg_buf(req->rq_repmsg, 0);
- /* FIXME: unpack only valid fields instead of memcpy, endianness */
- memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
- req->rq_status = obd_getattr(conn, &repbody->oa, NULL);
- RETURN(0);
-}
-
-static int ost_statfs(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- struct obd_statfs *osfs;
- int rc, size = sizeof(*osfs);
- ENTRY;
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
-
- osfs = lustre_msg_buf(req->rq_repmsg, 0);
- memset(osfs, 0, size);
-
- rc = obd_statfs(conn, osfs);
- if (rc) {
- CERROR("ost: statfs failed: rc %d\n", rc);
- req->rq_status = rc;
- RETURN(rc);
- }
- obd_statfs_pack(osfs, osfs);
-
- RETURN(0);
-}
-
-static int ost_open(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- struct ost_body *body, *repbody;
- int rc, size = sizeof(*body);
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
-
- repbody = lustre_msg_buf(req->rq_repmsg, 0);
- /* FIXME: unpack only valid fields instead of memcpy, endianness */
- memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
- req->rq_status = obd_open(conn, &repbody->oa, NULL);
- RETURN(0);
-}
-
-static int ost_close(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- struct ost_body *body, *repbody;
- int rc, size = sizeof(*body);
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
-
- repbody = lustre_msg_buf(req->rq_repmsg, 0);
- /* FIXME: unpack only valid fields instead of memcpy, endianness */
- memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
- req->rq_status = obd_close(conn, &repbody->oa, NULL);
- RETURN(0);
-}
-
-static int ost_create(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- struct ost_body *body, *repbody;
- int rc, size = sizeof(*body);
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
-
- repbody = lustre_msg_buf(req->rq_repmsg, 0);
- /* FIXME: unpack only valid fields instead of memcpy, endianness */
- memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
- req->rq_status = obd_create(conn, &repbody->oa, NULL);
- RETURN(0);
-}
-
-static int ost_punch(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- struct ost_body *body, *repbody;
- int rc, size = sizeof(*body);
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
-
- if ((NTOH__u32(body->oa.o_valid) & (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS))!=
- (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS))
- RETURN(-EINVAL);
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
-
- repbody = lustre_msg_buf(req->rq_repmsg, 0);
- /* FIXME: unpack only valid fields instead of memcpy, endianness */
- memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
- req->rq_status = obd_punch(conn, &repbody->oa, NULL,
- repbody->oa.o_size, repbody->oa.o_blocks);
- RETURN(0);
-}
-
-static int ost_setattr(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- struct ost_body *body, *repbody;
- int rc, size = sizeof(*body);
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
-
- repbody = lustre_msg_buf(req->rq_repmsg, 0);
- /* FIXME: unpack only valid fields instead of memcpy, endianness */
- memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
- req->rq_status = obd_setattr(conn, &repbody->oa, NULL);
- RETURN(0);
-}
-
-static int ost_bulk_timeout(void *data)
-{
- struct ptlrpc_bulk_desc *desc = data;
-
- ENTRY;
- recovd_conn_fail(desc->bd_connection);
- RETURN(1);
-}
-
-static int ost_brw_read(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- struct ptlrpc_bulk_desc *desc;
- void *tmp1, *tmp2, *end2;
- struct niobuf_remote *remote_nb;
- struct niobuf_local *local_nb = NULL;
- struct obd_ioobj *ioo;
- struct ost_body *body;
- struct l_wait_info lwi;
- void *desc_priv = NULL;
- int rc, cmd, i, j, objcount, niocount, size = sizeof(*body);
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- tmp1 = lustre_msg_buf(req->rq_reqmsg, 1);
- tmp2 = lustre_msg_buf(req->rq_reqmsg, 2);
- end2 = (char *)tmp2 + req->rq_reqmsg->buflens[2];
- objcount = req->rq_reqmsg->buflens[1] / sizeof(*ioo);
- niocount = req->rq_reqmsg->buflens[2] / sizeof(*remote_nb);
- cmd = OBD_BRW_READ;
-
- if (OBD_FAIL_CHECK(OBD_FAIL_OST_BRW_READ_BULK))
- GOTO(out, rc = 0);
-
- for (i = 0; i < objcount; i++) {
- ost_unpack_ioo(&tmp1, &ioo);
- if (tmp2 + ioo->ioo_bufcnt > end2) {
- LBUG();
- GOTO(out, rc = -EFAULT);
- }
- for (j = 0; j < ioo->ioo_bufcnt; j++)
- ost_unpack_niobuf(&tmp2, &remote_nb);
- }
-
- OBD_ALLOC(local_nb, sizeof(*local_nb) * niocount);
- if (local_nb == NULL)
- GOTO(out, rc = -ENOMEM);
-
- /* The unpackers move tmp1 and tmp2, so reset them before using */
- ioo = lustre_msg_buf(req->rq_reqmsg, 1);
- remote_nb = lustre_msg_buf(req->rq_reqmsg, 2);
- req->rq_status = obd_preprw(cmd, conn, objcount, ioo, niocount,
- remote_nb, local_nb, &desc_priv);
-
- if (req->rq_status)
- GOTO(out, rc = 0);
-
- desc = ptlrpc_prep_bulk(req->rq_connection);
- if (desc == NULL)
- GOTO(out_local, rc = -ENOMEM);
- desc->bd_portal = OST_BULK_PORTAL;
-
- for (i = 0; i < niocount; i++) {
- struct ptlrpc_bulk_page *bulk = ptlrpc_prep_bulk_page(desc);
-
- if (bulk == NULL)
- GOTO(out_bulk, rc = -ENOMEM);
- bulk->bp_xid = remote_nb[i].xid;
- bulk->bp_buf = local_nb[i].addr;
- bulk->bp_buflen = remote_nb[i].len;
- }
-
- rc = ptlrpc_send_bulk(desc);
- if (rc)
- GOTO(out_bulk, rc);
-
- lwi = LWI_TIMEOUT(obd_timeout * HZ, ost_bulk_timeout, desc);
- rc = l_wait_event(desc->bd_waitq, desc->bd_flags &PTL_BULK_FL_SENT, &lwi);
- if (rc) {
- LASSERT(rc == -ETIMEDOUT);
- GOTO(out_bulk, rc);
- }
-
- req->rq_status = obd_commitrw(cmd, conn, objcount, ioo, niocount,
- local_nb, desc_priv);
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
-
-out_bulk:
- ptlrpc_free_bulk(desc);
-out_local:
- OBD_FREE(local_nb, sizeof(*local_nb) * niocount);
-out:
- if (rc)
- ptlrpc_error(req->rq_svc, req);
- else
- ptlrpc_reply(req->rq_svc, req);
- RETURN(rc);
-}
-
-static int ost_brw_write(struct ptlrpc_request *req)
-{
- struct lustre_handle *conn = (struct lustre_handle *)req->rq_reqmsg;
- struct ptlrpc_bulk_desc *desc;
- struct niobuf_remote *remote_nb;
- struct niobuf_local *local_nb, *lnb;
- struct obd_ioobj *ioo;
- struct ost_body *body;
- int cmd, rc, i, j, objcount, niocount, size[2] = {sizeof(*body)};
- void *tmp1, *tmp2, *end2;
- void *desc_priv = NULL;
- int reply_sent = 0;
- struct ptlrpc_service *srv;
- struct l_wait_info lwi;
- __u32 xid;
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- tmp1 = lustre_msg_buf(req->rq_reqmsg, 1);
- tmp2 = lustre_msg_buf(req->rq_reqmsg, 2);
- end2 = (char *)tmp2 + req->rq_reqmsg->buflens[2];
- objcount = req->rq_reqmsg->buflens[1] / sizeof(*ioo);
- niocount = req->rq_reqmsg->buflens[2] / sizeof(*remote_nb);
- cmd = OBD_BRW_WRITE;
-
- for (i = 0; i < objcount; i++) {
- ost_unpack_ioo((void *)&tmp1, &ioo);
- if (tmp2 + ioo->ioo_bufcnt > end2) {
- rc = -EFAULT;
- break;
- }
- for (j = 0; j < ioo->ioo_bufcnt; j++)
- ost_unpack_niobuf((void *)&tmp2, &remote_nb);
- }
-
- size[1] = niocount * sizeof(*remote_nb);
- rc = lustre_pack_msg(2, size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- GOTO(out, rc);
- remote_nb = lustre_msg_buf(req->rq_repmsg, 1);
-
- OBD_ALLOC(local_nb, niocount * sizeof(*local_nb));
- if (local_nb == NULL)
- GOTO(out, rc = -ENOMEM);
-
- /* The unpackers move tmp1 and tmp2, so reset them before using */
- tmp1 = lustre_msg_buf(req->rq_reqmsg, 1);
- tmp2 = lustre_msg_buf(req->rq_reqmsg, 2);
- req->rq_status = obd_preprw(cmd, conn, objcount, tmp1, niocount, tmp2,
- local_nb, &desc_priv);
- if (req->rq_status)
- GOTO(out_free, rc = 0); /* XXX is this correct? */
-
- if (OBD_FAIL_CHECK(OBD_FAIL_OST_BRW_WRITE_BULK))
- GOTO(fail_preprw, rc = 0);
-
- desc = ptlrpc_prep_bulk(req->rq_connection);
- if (desc == NULL)
- GOTO(fail_preprw, rc = -ENOMEM);
- desc->bd_ptl_ev_hdlr = NULL;
- desc->bd_portal = OSC_BULK_PORTAL;
- desc->bd_desc_private = desc_priv;
- memcpy(&(desc->bd_conn), &conn, sizeof(conn));
-
- srv = req->rq_obd->u.ost.ost_service;
- spin_lock(&srv->srv_lock);
- xid = srv->srv_xid++; /* single xid for all pages */
- spin_unlock(&srv->srv_lock);
-
- for (i = 0, lnb = local_nb; i < niocount; i++, lnb++) {
- struct ptlrpc_bulk_page *bulk;
-
- bulk = ptlrpc_prep_bulk_page(desc);
- if (bulk == NULL)
- GOTO(fail_bulk, rc = -ENOMEM);
-
- bulk->bp_xid = xid; /* single xid for all pages */
-
- bulk->bp_buf = lnb->addr;
- bulk->bp_page = lnb->page;
- bulk->bp_flags = lnb->flags;
- bulk->bp_dentry = lnb->dentry;
- bulk->bp_buflen = lnb->len;
- bulk->bp_cb = NULL;
-
- /* this advances remote_nb */
- ost_pack_niobuf((void **)&remote_nb, lnb->offset, lnb->len, 0,
- bulk->bp_xid);
- }
-
- rc = ptlrpc_register_bulk(desc);
- if (rc)
- GOTO(fail_bulk, rc);
-
- reply_sent = 1;
- ptlrpc_reply(req->rq_svc, req);
-
- lwi = LWI_TIMEOUT(obd_timeout * HZ, ost_bulk_timeout, desc);
- rc = l_wait_event(desc->bd_waitq, desc->bd_flags & PTL_BULK_FL_RCVD,
- &lwi);
- if (rc) {
- if (rc != -ETIMEDOUT)
- LBUG();
- GOTO(fail_bulk, rc);
- }
-
- rc = obd_commitrw(cmd, conn, objcount, tmp1, niocount, local_nb,
- desc->bd_desc_private);
- ptlrpc_free_bulk(desc);
- EXIT;
-out_free:
- OBD_FREE(local_nb, niocount * sizeof(*local_nb));
-out:
- if (!reply_sent) {
- if (rc) {
- OBD_FREE(req->rq_repmsg, req->rq_replen);
- req->rq_repmsg = NULL;
- ptlrpc_error(req->rq_svc, req);
- } else
- ptlrpc_reply(req->rq_svc, req);
- }
- return rc;
-
-fail_bulk:
- ptlrpc_free_bulk(desc);
-fail_preprw:
- /* FIXME: how do we undo the preprw? */
- goto out_free;
-}
-
-static int ost_handle(struct ptlrpc_request *req)
-{
- int rc;
- ENTRY;
-
- rc = lustre_unpack_msg(req->rq_reqmsg, req->rq_reqlen);
- if (rc || OBD_FAIL_CHECK(OBD_FAIL_OST_HANDLE_UNPACK)) {
- CERROR("lustre_ost: Invalid request\n");
- GOTO(out, rc);
- }
-
- if (req->rq_reqmsg->opc != OST_CONNECT &&
- req->rq_export == NULL) {
- CERROR("lustre_ost: operation %d on unconnected OST\n",
- req->rq_reqmsg->opc);
- GOTO(out, rc = -ENOTCONN);
- }
-
- if (strcmp(req->rq_obd->obd_type->typ_name, "ost") != 0)
- GOTO(out, rc = -EINVAL);
-
- switch (req->rq_reqmsg->opc) {
- case OST_CONNECT:
- CDEBUG(D_INODE, "connect\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_CONNECT_NET, 0);
- rc = target_handle_connect(req);
- break;
- case OST_DISCONNECT:
- CDEBUG(D_INODE, "disconnect\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_DISCONNECT_NET, 0);
- rc = target_handle_disconnect(req);
- break;
- case OST_CREATE:
- CDEBUG(D_INODE, "create\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_CREATE_NET, 0);
- rc = ost_create(req);
- break;
- case OST_DESTROY:
- CDEBUG(D_INODE, "destroy\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_DESTROY_NET, 0);
- rc = ost_destroy(req);
- break;
- case OST_GETATTR:
- CDEBUG(D_INODE, "getattr\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_GETATTR_NET, 0);
- rc = ost_getattr(req);
- break;
- case OST_SETATTR:
- CDEBUG(D_INODE, "setattr\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_SETATTR_NET, 0);
- rc = ost_setattr(req);
- break;
- case OST_OPEN:
- CDEBUG(D_INODE, "open\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_OPEN_NET, 0);
- rc = ost_open(req);
- break;
- case OST_CLOSE:
- CDEBUG(D_INODE, "close\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_CLOSE_NET, 0);
- rc = ost_close(req);
- break;
- case OST_WRITE:
- CDEBUG(D_INODE, "write\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_BRW_NET, 0);
- rc = ost_brw_write(req);
- /* ost_brw sends its own replies */
- RETURN(rc);
- case OST_READ:
- CDEBUG(D_INODE, "read\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_BRW_NET, 0);
- rc = ost_brw_read(req);
- /* ost_brw sends its own replies */
- RETURN(rc);
- case OST_PUNCH:
- CDEBUG(D_INODE, "punch\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_PUNCH_NET, 0);
- rc = ost_punch(req);
- break;
- case OST_STATFS:
- CDEBUG(D_INODE, "statfs\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_STATFS_NET, 0);
- rc = ost_statfs(req);
- break;
- case LDLM_ENQUEUE:
- CDEBUG(D_INODE, "enqueue\n");
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_ENQUEUE, 0);
- rc = ldlm_handle_enqueue(req);
- break;
- case LDLM_CONVERT:
- CDEBUG(D_INODE, "convert\n");
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_CONVERT, 0);
- rc = ldlm_handle_convert(req);
- break;
- case LDLM_CANCEL:
- CDEBUG(D_INODE, "cancel\n");
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_CANCEL, 0);
- rc = ldlm_handle_cancel(req);
- break;
- case LDLM_BL_CALLBACK:
- case LDLM_CP_CALLBACK:
- CDEBUG(D_INODE, "callback\n");
- CERROR("callbacks should not happen on OST\n");
- LBUG();
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_BL_CALLBACK, 0);
- break;
- default:
- req->rq_status = -ENOTSUPP;
- rc = ptlrpc_error(req->rq_svc, req);
- RETURN(rc);
- }
-
- EXIT;
-out:
- //req->rq_status = rc;
- if (rc) {
- CERROR("ost: processing error (opcode=%d): %d\n",
- req->rq_reqmsg->opc, rc);
- ptlrpc_error(req->rq_svc, req);
- } else {
- CDEBUG(D_INODE, "sending reply\n");
- if (req->rq_repmsg == NULL)
- CERROR("handler for opcode %d returned rc=0 without "
- "creating rq_repmsg; needs to return rc != "
- "0!\n", req->rq_reqmsg->opc);
- ptlrpc_reply(req->rq_svc, req);
- }
-
- return 0;
-}
-
-/* mount the file system (secretly) */
-static int ost_setup(struct obd_device *obddev, obd_count len, void *buf)
-{
- struct obd_ioctl_data* data = buf;
- struct ost_obd *ost = &obddev->u.ost;
- struct obd_device *tgt;
- int err;
- int i;
- ENTRY;
-
- if (data->ioc_inllen1 < 1) {
- CERROR("requires a TARGET OBD UUID\n");
- RETURN(-EINVAL);
- }
- if (data->ioc_inllen1 > 37) {
- CERROR("OBD UUID must be less than 38 characters\n");
- RETURN(-EINVAL);
- }
-
- MOD_INC_USE_COUNT;
- tgt = class_uuid2obd(data->ioc_inlbuf1);
- if (!tgt || !(tgt->obd_flags & OBD_ATTACHED) ||
- !(tgt->obd_flags & OBD_SET_UP)) {
- CERROR("device not attached or not set up (%d)\n",
- data->ioc_dev);
- GOTO(error_dec, err = -EINVAL);
- }
-
- err = obd_connect(&ost->ost_conn, tgt, NULL, NULL, NULL);
- if (err) {
- CERROR("fail to connect to device %d\n", data->ioc_dev);
- GOTO(error_dec, err = -EINVAL);
- }
-
- ost->ost_service = ptlrpc_init_svc(OST_NEVENTS, OST_NBUFS,
- OST_BUFSIZE, OST_MAXREQSIZE,
- OST_REQUEST_PORTAL, OSC_REPLY_PORTAL,
- "self", ost_handle, "ost");
- if (!ost->ost_service) {
- CERROR("failed to start service\n");
- GOTO(error_disc, err = -EINVAL);
- }
-
- for (i = 0; i < OST_NUM_THREADS; i++) {
- char name[32];
- sprintf(name, "ll_ost_%02d", i);
- err = ptlrpc_start_thread(obddev, ost->ost_service, name);
- if (err) {
- CERROR("error starting thread #%d: rc %d\n", i, err);
- GOTO(error_disc, err = -EINVAL);
- }
- }
-
- RETURN(0);
-
-error_disc:
- obd_disconnect(&ost->ost_conn);
-error_dec:
- MOD_DEC_USE_COUNT;
- RETURN(err);
-}
-
-static int ost_cleanup(struct obd_device * obddev)
-{
- struct ost_obd *ost = &obddev->u.ost;
- int err;
-
- ENTRY;
-
- if ( !list_empty(&obddev->obd_exports) ) {
- CERROR("still has clients!\n");
- RETURN(-EBUSY);
- }
-
- ptlrpc_stop_all_threads(ost->ost_service);
- ptlrpc_unregister_service(ost->ost_service);
-
- err = obd_disconnect(&ost->ost_conn);
- if (err) {
- CERROR("lustre ost: fail to disconnect device\n");
- RETURN(-EINVAL);
- }
-
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-int ost_attach(struct obd_device *dev, obd_count len, void *data)
-{
- return lprocfs_reg_obd(dev, status_var_nm_1, dev);
-}
-
-int ost_detach(struct obd_device *dev)
-{
- return lprocfs_dereg_obd(dev);
-
-}
-
-
-
-/* use obd ops to offer management infrastructure */
-static struct obd_ops ost_obd_ops = {
- o_attach: ost_attach,
- o_detach: ost_detach,
- o_setup: ost_setup,
- o_cleanup: ost_cleanup,
-};
-
-static int __init ost_init(void)
-{
- int rc;
-
- rc = class_register_type(&ost_obd_ops, status_class_var,
- LUSTRE_OST_NAME);
- RETURN(rc);
-
-}
-
-static void __exit ost_exit(void)
-{
-
- class_unregister_type(LUSTRE_OST_NAME);
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Object Storage Target (OST) v0.01");
-MODULE_LICENSE("GPL");
-
-module_init(ost_init);
-module_exit(ost_exit);
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
---- lum-pristine/arch/ia64/mm/init.c Fri Nov 9 17:26:17 2001
-+++ lum/arch/ia64/mm/init.c Thu Aug 1 18:07:35 2002
-@@ -37,6 +37,12 @@
-
- static unsigned long totalram_pages;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int
- do_check_pgt_cache (int low, int high)
- {
---- lum-pristine/arch/i386/mm/init.c Fri Dec 21 12:41:53 2001
-+++ lum/arch/i386/mm/init.c Thu Aug 1 18:07:35 2002
-@@ -43,6 +43,12 @@
- static unsigned long totalram_pages;
- static unsigned long totalhigh_pages;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int do_check_pgt_cache(int low, int high)
- {
- int freed = 0;
---- lum-pristine/drivers/block/blkpg.c Mon Feb 25 14:37:57 2002
-+++ lum/drivers/block/blkpg.c Thu Aug 1 18:07:35 2002
-@@ -294,3 +294,38 @@
- }
-
- EXPORT_SYMBOL(blk_ioctl);
-+
-+#define NUM_DEV_NO_WRITE 16
-+static int dev_no_write[NUM_DEV_NO_WRITE];
-+
-+/*
-+ * Debug code for turning block devices "read-only" (will discard writes
-+ * silently). This is for filesystem crash/recovery testing.
-+ */
-+void dev_set_rdonly(kdev_t dev, int no_write)
-+{
-+ if (dev) {
-+ printk(KERN_WARNING "Turning device %s read-only\n",
-+ bdevname(dev));
-+ dev_no_write[no_write] = 0xdead0000 + dev;
-+ }
-+}
-+
-+int dev_check_rdonly(kdev_t dev) {
-+ int i;
-+
-+ for (i = 0; i < NUM_DEV_NO_WRITE; i++) {
-+ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 &&
-+ dev == (dev_no_write[i] & 0xffff))
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+void dev_clear_rdonly(int no_write) {
-+ dev_no_write[no_write] = 0;
-+}
-+
-+EXPORT_SYMBOL(dev_set_rdonly);
-+EXPORT_SYMBOL(dev_check_rdonly);
-+EXPORT_SYMBOL(dev_clear_rdonly);
---- lum-pristine/drivers/block/loop.c Fri Dec 21 12:41:53 2001
-+++ lum/drivers/block/loop.c Thu Aug 1 18:07:35 2002
-@@ -471,6 +471,11 @@
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (dev_check_rdonly(rbh->b_rdev))
-+ goto err;
-+#endif
-+
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
---- lum-pristine/drivers/ide/ide-disk.c Fri Dec 21 12:41:54 2001
-+++ lum/drivers/ide/ide-disk.c Thu Aug 1 18:07:35 2002
-@@ -367,6 +367,12 @@
- */
- static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
- {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
-+ ide_end_request(1, HWGROUP(drive));
-+ return ide_stopped;
-+ }
-+#endif
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
- OUT_BYTE(0x00, IDE_FEATURE_REG);
---- lum-pristine/fs/ext3/Makefile Fri Dec 21 12:41:55 2001
-+++ lum/fs/ext3/Makefile Thu Aug 1 18:07:35 2002
-@@ -9,6 +9,8 @@
-
- O_TARGET := ext3.o
-
-+export-objs := super.o
-+
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
---- lum-pristine/fs/ext3/super.c Mon Feb 25 14:38:08 2002
-+++ lum/fs/ext3/super.c Thu Aug 1 18:07:35 2002
-@@ -1744,7 +1744,7 @@
- unregister_filesystem(&ext3_fs_type);
- }
-
--EXPORT_NO_SYMBOLS;
-+EXPORT_SYMBOL(ext3_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
- MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
---- lum-pristine/fs/jbd/commit.c Mon Feb 25 14:38:08 2002
-+++ lum/fs/jbd/commit.c Thu Aug 1 18:07:35 2002
-@@ -475,7 +475,7 @@
- transaction's t_log_list queue, and metadata buffers are on
- the t_iobuf_list queue.
-
-- Wait for the transactions in reverse order. That way we are
-+ Wait for the buffers in reverse order. That way we are
- less likely to be woken up until all IOs have completed, and
- so we incur less scheduling load.
- */
-@@ -566,8 +566,10 @@
-
- jbd_debug(3, "JBD: commit phase 6\n");
-
-- if (is_journal_aborted(journal))
-+ if (is_journal_aborted(journal)) {
-+ unlock_journal(journal);
- goto skip_commit;
-+ }
-
- /* Done it all: now write the commit record. We should have
- * cleaned up our previous buffers by now, so if we are in abort
-@@ -577,6 +579,7 @@
- descriptor = journal_get_descriptor_buffer(journal);
- if (!descriptor) {
- __journal_abort_hard(journal);
-+ unlock_journal(journal);
- goto skip_commit;
- }
-
-@@ -600,7 +603,6 @@
- put_bh(bh); /* One for getblk() */
- journal_unlock_journal_head(descriptor);
- }
-- lock_journal(journal);
-
- /* End of a transaction! Finally, we can do checkpoint
- processing: any buffers committed as a result of this
-@@ -609,6 +611,25 @@
-
- skip_commit:
-
-+ /* Call any callbacks that had been registered for handles in this
-+ * transaction. It is up to the callback to free any allocated
-+ * memory.
-+ */
-+ if (!list_empty(&commit_transaction->t_jcb)) {
-+ struct list_head *p, *n;
-+ int error = is_journal_aborted(journal);
-+
-+ list_for_each_safe(p, n, &commit_transaction->t_jcb) {
-+ struct journal_callback *jcb;
-+
-+ jcb = list_entry(p, struct journal_callback, jcb_list);
-+ list_del(p);
-+ jcb->jcb_func(jcb, error);
-+ }
-+ }
-+
-+ lock_journal(journal);
-+
- jbd_debug(3, "JBD: commit phase 7\n");
-
- J_ASSERT(commit_transaction->t_sync_datalist == NULL);
---- lum-pristine/fs/jbd/journal.c Mon Feb 25 14:38:08 2002
-+++ lum/fs/jbd/journal.c Thu Aug 1 18:07:35 2002
-@@ -58,6 +58,7 @@
- #endif
- EXPORT_SYMBOL(journal_flush);
- EXPORT_SYMBOL(journal_revoke);
-+EXPORT_SYMBOL(journal_callback_set);
-
- EXPORT_SYMBOL(journal_init_dev);
- EXPORT_SYMBOL(journal_init_inode);
---- lum-pristine/fs/jbd/transaction.c Mon Feb 25 14:38:08 2002
-+++ lum/fs/jbd/transaction.c Thu Aug 1 18:07:35 2002
-@@ -57,6 +57,7 @@
- transaction->t_state = T_RUNNING;
- transaction->t_tid = journal->j_transaction_sequence++;
- transaction->t_expires = jiffies + journal->j_commit_interval;
-+ INIT_LIST_HEAD(&transaction->t_jcb);
-
- /* Set up the commit timer for the new transaction. */
- J_ASSERT (!journal->j_commit_timer_active);
-@@ -201,6 +202,20 @@
- return 0;
- }
-
-+/* Allocate a new handle. This should probably be in a slab... */
-+static handle_t *new_handle(int nblocks)
-+{
-+ handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+ if (!handle)
-+ return NULL;
-+ memset(handle, 0, sizeof (handle_t));
-+ handle->h_buffer_credits = nblocks;
-+ handle->h_ref = 1;
-+ INIT_LIST_HEAD(&handle->h_jcb);
-+
-+ return handle;
-+}
-+
- /*
- * Obtain a new handle.
- *
-@@ -227,14 +242,11 @@
- handle->h_ref++;
- return handle;
- }
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = new_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = start_this_handle(journal, handle);
-@@ -333,14 +345,11 @@
-
- if (is_journal_aborted(journal))
- return ERR_PTR(-EIO);
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = new_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = try_start_this_handle(journal, handle);
-@@ -1328,6 +1337,28 @@
- #endif
-
- /*
-+ * Register a callback function for this handle. The function will be
-+ * called when the transaction that this handle is part of has been
-+ * committed to disk with the original callback data struct and the
-+ * error status of the journal as parameters. There is no guarantee of
-+ * ordering between handles within a single transaction, nor between
-+ * callbacks registered on the same handle.
-+ *
-+ * The caller is responsible for allocating the journal_callback struct.
-+ * This is to allow the caller to add as much extra data to the callback
-+ * as needed, but reduce the overhead of multiple allocations. The caller
-+ * allocated struct must start with a struct journal_callback at offset 0,
-+ * and has the caller-specific data afterwards.
-+ */
-+void journal_callback_set(handle_t *handle,
-+ void (*func)(struct journal_callback *jcb, int error),
-+ struct journal_callback *jcb)
-+{
-+ list_add(&jcb->jcb_list, &handle->h_jcb);
-+ jcb->jcb_func = func;
-+}
-+
-+/*
- * All done for a particular handle.
- *
- * There is not much action needed here. We just return any remaining
-@@ -1383,7 +1415,10 @@
- wake_up(&journal->j_wait_transaction_locked);
- }
-
-- /*
-+ /* Move callbacks from the handle to the transaction. */
-+ list_splice(&handle->h_jcb, &transaction->t_jcb);
-+
-+ /*
- * If the handle is marked SYNC, we need to set another commit
- * going! We also want to force a commit if the current
- * transaction is occupying too much of the log, or if the
---- lum-pristine/include/linux/blkdev.h Mon Nov 26 08:29:17 2001
-+++ lum/include/linux/blkdev.h Mon Aug 12 11:48:39 2002
-@@ -228,4 +228,8 @@
- return retval;
- }
-
-+#define CONFIG_DEV_RDONLY
-+void dev_set_rdonly(kdev_t, int);
-+int dev_check_rdonly(kdev_t);
-+void dev_clear_rdonly(int);
- #endif
---- lum-pristine/include/linux/slab.h Fri Dec 21 12:42:04 2001
-+++ lum/include/linux/slab.h Mon Aug 12 11:48:38 2002
-@@ -57,6 +57,7 @@
- extern int kmem_cache_shrink(kmem_cache_t *);
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
-
- extern void *kmalloc(size_t, int);
- extern void kfree(const void *);
---- lum-pristine/include/linux/jbd.h Mon Feb 25 14:38:13 2002
-+++ lum/include/linux/jbd.h Mon Aug 12 11:50:09 2002
-@@ -249,6 +249,13 @@
- return bh->b_private;
- }
-
-+#define HAVE_JOURNAL_CALLBACK_STATUS
-+struct journal_callback {
-+ struct list_head jcb_list;
-+ void (*jcb_func)(struct journal_callback *jcb, int error);
-+ /* user data goes here */
-+};
-+
- struct jbd_revoke_table_s;
-
- /* The handle_t type represents a single atomic update being performed
-@@ -279,6 +286,12 @@
- operations */
- int h_err;
-
-+ /* List of application registered callbacks for this handle.
-+ * The function(s) will be called after the transaction that
-+ * this handle is part of has been committed to disk.
-+ */
-+ struct list_head h_jcb;
-+
- /* Flags */
- unsigned int h_sync: 1; /* sync-on-close */
- unsigned int h_jdata: 1; /* force data journaling */
-@@ -398,6 +411,10 @@
-
- /* How many handles used this transaction? */
- int t_handle_count;
-+
-+ /* List of registered callback functions for this transaction.
-+ * Called when the transaction is committed. */
-+ struct list_head t_jcb;
- };
-
-
-@@ -646,6 +663,9 @@
- extern int journal_try_to_free_buffers(journal_t *, struct page *, int);
- extern int journal_stop(handle_t *);
- extern int journal_flush (journal_t *);
-+extern void journal_callback_set(handle_t *handle,
-+ void (*fn)(struct journal_callback *,int),
-+ struct journal_callback *jcb);
-
- extern void journal_lock_updates (journal_t *);
- extern void journal_unlock_updates (journal_t *);
---- lum-pristine/kernel/ksyms.c Mon Feb 25 14:38:13 2002
-+++ lum/kernel/ksyms.c Thu Aug 1 18:07:35 2002
-@@ -271,6 +271,12 @@
- EXPORT_SYMBOL(lock_may_write);
- EXPORT_SYMBOL(dcache_readdir);
-
-+/* lustre */
-+EXPORT_SYMBOL(panic_notifier_list);
-+EXPORT_SYMBOL(pagecache_lock);
-+EXPORT_SYMBOL(do_kern_mount);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+
- /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
- EXPORT_SYMBOL(default_llseek);
- EXPORT_SYMBOL(dentry_open);
---- lum-pristine/include/linux/dcache.h Thu Nov 22 14:46:18 2001
-+++ lum/include/linux/dcache.h Mon Aug 12 00:02:29 2002
-@@ -6,6 +6,34 @@
- #include <asm/atomic.h>
- #include <linux/mount.h>
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_LINK2 (1<<4)
-+#define IT_SYMLINK (1<<5)
-+#define IT_UNLINK (1<<6)
-+#define IT_RMDIR (1<<7)
-+#define IT_RENAME (1<<8)
-+#define IT_RENAME2 (1<<9)
-+#define IT_READDIR (1<<10)
-+#define IT_GETATTR (1<<11)
-+#define IT_SETATTR (1<<12)
-+#define IT_READLINK (1<<13)
-+#define IT_MKNOD (1<<14)
-+#define IT_LOOKUP (1<<15)
-+
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -78,6 +106,7 @@
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
- struct super_block * d_sb; /* The root of the dentry tree */
-+ struct lookup_intent *d_it;
- unsigned long d_vfs_flags;
- void * d_fsdata; /* fs-specific data */
- unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
-@@ -91,6 +119,8 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *, struct lookup_intent *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
---- lum-pristine/include/linux/fs.h Mon Aug 12 11:02:53 2002
-+++ lum/include/linux/fs.h Mon Aug 12 11:48:38 2002
-@@ -536,6 +536,7 @@
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_intent;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -779,7 +780,9 @@
- extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
- extern int vfs_rmdir(struct inode *, struct dentry *);
- extern int vfs_unlink(struct inode *, struct dentry *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it);
-
- /*
- * File types
-@@ -840,6 +843,7 @@
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -986,7 +990,7 @@
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
--
-+struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data);
- #define kern_umount mntput
-
- extern int vfs_statfs(struct super_block *, struct statfs *);
-@@ -1307,6 +1311,7 @@
- extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
-
- extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
-+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
- extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
- extern int FASTCALL(path_walk(const char *, struct nameidata *));
- extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
-@@ -1317,6 +1322,8 @@
- extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
- #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
- #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
-+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
-+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
-
- extern void iput(struct inode *);
- extern void force_delete(struct inode *);
---- lum-pristine/fs/dcache.c Mon Feb 25 14:38:08 2002
-+++ lum/fs/dcache.c Thu Aug 1 18:07:35 2002
-@@ -617,6 +617,7 @@
- dentry->d_op = NULL;
- dentry->d_fsdata = NULL;
- dentry->d_mounted = 0;
-+ dentry->d_it = NULL;
- INIT_LIST_HEAD(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_subdirs);
---- lum-pristine/fs/nfsd/vfs.c Fri Dec 21 12:41:55 2001
-+++ lum/fs/nfsd/vfs.c Thu Aug 1 18:07:35 2002
-@@ -1285,7 +1285,7 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
---- lum-pristine/fs/namei.c Mon Feb 25 14:38:09 2002
-+++ lum/fs/namei.c Mon Aug 12 11:47:56 2002
-@@ -94,6 +94,14 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct dentry *de, struct lookup_intent *it)
-+{
-+ if (de->d_op && de->d_op->d_intent_release)
-+ de->d_op->d_intent_release(de, it);
-+ de->d_it = NULL;
-+}
-+
-+
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
-@@ -260,10 +268,19 @@
- * Internal lookup() using the new generic dcache.
- * SMP-safe
- */
--static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * dentry = d_lookup(parent, name);
-
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -281,7 +298,8 @@
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
--static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * result;
- struct inode *dir = parent->d_inode;
-@@ -300,6 +318,9 @@
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- lock_kernel();
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -321,6 +342,12 @@
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
- }
- return result;
- }
-@@ -445,7 +472,8 @@
- *
- * We expect 'base' to be positive and a directory.
- */
--int link_path_walk(const char * name, struct nameidata *nd)
-+int link_path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
- struct inode *inode;
-@@ -518,9 +546,9 @@
- break;
- }
- /* This does the actual lookups.. */
-- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
- if (!dentry) {
-- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -554,7 +582,7 @@
- nd->dentry = dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -581,9 +609,9 @@
- if (err < 0)
- break;
- }
-- dentry = cached_lookup(nd->dentry, &this, 0);
-+ dentry = cached_lookup(nd->dentry, &this, 0, it);
- if (!dentry) {
-- dentry = real_lookup(nd->dentry, &this, 0);
-+ dentry = real_lookup(nd->dentry, &this, 0, it);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -607,7 +635,8 @@
- goto no_inode;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op || (!inode->i_op->lookup &&
-+ !inode->i_op->lookup2))
- break;
- }
- goto return_base;
-@@ -630,12 +660,23 @@
- return err;
- }
-
-+int link_path_walk(const char * name, struct nameidata *nd)
-+{
-+ return link_path_walk_it(name, nd, NULL);
-+}
-+
-+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
-+{
-+ current->total_link_count = 0;
-+ return link_path_walk_it(name, nd, it);
-+}
-+
- int path_walk(const char * name, struct nameidata *nd)
- {
- current->total_link_count = 0;
-- return link_path_walk(name, nd);
-+ return link_path_walk_it(name, nd, NULL);
- }
-
- /* SMP-safe */
- /* returns 1 if everything is done */
- static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
-@@ -742,7 +786,8 @@
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -765,13 +810,16 @@
- goto out;
- }
-
-- dentry = cached_lookup(base, name, 0);
-+ dentry = cached_lookup(base, name, 0, it);
- if (!dentry) {
- struct dentry *new = d_alloc(base, name);
- dentry = ERR_PTR(-ENOMEM);
- if (!new)
- goto out;
- lock_kernel();
-+ if (inode->i_op->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -783,6 +831,12 @@
- return dentry;
- }
-
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+{
-+ return lookup_hash_it(name, base, NULL);
-+}
-+
-+
- /* SMP-safe */
- struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
- {
-@@ -804,7 +858,7 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash_it(&this, base, NULL);
- access:
- return ERR_PTR(-EACCES);
- }
-@@ -836,6 +890,23 @@
- return err;
- }
-
-+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ char *tmp;
-+ int err;
-+
-+ tmp = getname(name);
-+ err = PTR_ERR(tmp);
-+ if (!IS_ERR(tmp)) {
-+ err = 0;
-+ if (path_init(tmp, flags, nd))
-+ err = path_walk_it(tmp, nd, it);
-+ putname(tmp);
-+ }
-+ return err;
-+}
-+
- /*
- * It's inline, so penalty for filesystems that don't use sticky bit is
- * minimal.
-@@ -970,7 +1041,8 @@
- * for symlinks (where the permissions are checked later).
- * SMP-safe
- */
--int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
-+int open_namei_it(const char *pathname, int flag, int mode,
-+ struct nameidata *nd, struct lookup_intent *it)
- {
- int acc_mode, error = 0;
- struct inode *inode;
-@@ -985,7 +1057,7 @@
- */
- if (!(flag & O_CREAT)) {
- if (path_init(pathname, lookup_flags(flag), nd))
-- error = path_walk(pathname, nd);
-+ error = path_walk_it(pathname, nd, it);
- if (error)
- return error;
- dentry = nd->dentry;
-@@ -994,6 +1067,10 @@
- /*
- * Create - we need to know the parent.
- */
-+ if (it) {
-+ it->it_mode = mode;
-+ it->it_op |= IT_CREAT;
-+ }
- if (path_init(pathname, LOOKUP_PARENT, nd))
- error = path_walk(pathname, nd);
- if (error)
-@@ -1011,7 +1089,7 @@
-
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1020,6 +1098,7 @@
- goto exit;
- }
-
-+ it->it_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
- error = vfs_create(dir->d_inode, dentry,
-@@ -1139,8 +1219,10 @@
- return 0;
-
- exit_dput:
-+ intent_release(dentry, it);
- dput(dentry);
- exit:
-+ intent_release(nd->dentry, it);
- path_release(nd);
- return error;
-
-@@ -1160,6 +1242,8 @@
- */
- UPDATE_ATIME(dentry->d_inode);
- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(dentry, it);
- dput(dentry);
- if (error)
- return error;
-@@ -1181,13 +1265,20 @@
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, NULL);
- putname(nd->last.name);
- goto do_last;
- }
-
-+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd)
-+{
-+ return open_namei_it(pathname, flag, mode, nd, NULL);
-+}
-+
-+
- /* SMP-safe */
--static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
-+static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
-
-@@ -1195,7 +1286,7 @@
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1241,6 +1332,7 @@
- char * tmp;
- struct dentry * dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode };
-
- if (S_ISDIR(mode))
- return -EPERM;
-@@ -1252,7 +1344,7 @@
- error = path_walk(tmp, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
-
- mode &= ~current->fs->umask;
-@@ -1270,6 +1363,7 @@
- default:
- error = -EINVAL;
- }
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1310,6 +1404,7 @@
- {
- int error = 0;
- char * tmp;
-+ struct lookup_intent it = { .it_op = IT_MKDIR, .it_mode = mode };
-
- tmp = getname(pathname);
- error = PTR_ERR(tmp);
-@@ -1321,11 +1416,12 @@
- error = path_walk(tmp, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 1);
-+ dentry = lookup_create(&nd, 1, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_mkdir(nd.dentry->d_inode, dentry,
- mode & ~current->fs->umask);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1407,6 +1504,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_RMDIR };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1429,10 +1527,11 @@
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1476,6 +1576,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_UNLINK };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1489,14 +1590,15 @@
- if (nd.last_type != LAST_NORM)
- goto exit1;
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
- if (nd.last.name[nd.last.len])
- goto slashes;
- error = vfs_unlink(nd.dentry->d_inode, dentry);
- exit2:
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1543,6 +1646,7 @@
- int error = 0;
- char * from;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_SYMLINK };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1557,10 +1661,12 @@
- error = path_walk(to, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ it.it_data = from;
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1626,6 +1732,7 @@
- int error;
- char * from;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_LINK };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1639,7 +1745,7 @@
-
- error = 0;
- if (path_init(from, LOOKUP_POSITIVE, &old_nd))
-- error = path_walk(from, &old_nd);
-+ error = path_walk_it(from, &old_nd, &it);
- if (error)
- goto exit;
- if (path_init(to, LOOKUP_PARENT, &nd))
-@@ -1648,10 +1755,12 @@
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-- new_dentry = lookup_create(&nd, 0);
-+ it.it_op = IT_LINK2;
-+ new_dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-+ intent_release(new_dentry, &it);
- dput(new_dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1694,7 +1803,8 @@
- * locking].
- */
- int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- struct inode *target;
-@@ -1754,6 +1864,7 @@
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- if (target) {
- if (!error)
- target->i_flags |= S_DEAD;
-@@ -1775,7 +1887,8 @@
- }
-
- int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -1806,6 +1919,7 @@
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- double_up(&old_dir->i_zombie, &new_dir->i_zombie);
- if (error)
- return error;
-@@ -1817,13 +1932,14 @@
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- if (S_ISDIR(old_dentry->d_inode->i_mode))
-- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
- else
-- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
- if (!error) {
- if (old_dir == new_dir)
- inode_dir_notify(old_dir, DN_RENAME);
-@@ -1840,6 +1956,7 @@
- int error = 0;
- struct dentry * old_dir, * new_dir;
- struct dentry * old_dentry, *new_dentry;
-+ struct lookup_intent it = { .it_op = IT_RENAME };
- struct nameidata oldnd, newnd;
-
- if (path_init(oldname, LOOKUP_PARENT, &oldnd))
-@@ -1868,7 +1985,7 @@
-
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -1884,18 +2003,21 @@
- if (newnd.last.name[newnd.last.len])
- goto exit4;
- }
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ it.it_op = IT_RENAME2;
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, &it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-
- lock_kernel();
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, &it);
- unlock_kernel();
-
-+ intent_release(new_dentry, &it);
- dput(new_dentry);
- exit4:
-+ intent_release(old_dentry, &it); // FIXME: release same intent twice!!!
- dput(old_dentry);
- exit3:
- double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
---- lum-pristine/fs/open.c Fri Oct 12 16:48:42 2001
-+++ lum/fs/open.c Sun Aug 11 15:26:29 2002
-@@ -19,6 +19,9 @@
- #include <asm/uaccess.h>
-
- #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
-+extern int path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it);
-+extern void intent_release(struct dentry *de, struct lookup_intent *it);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -94,12 +97,13 @@
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
- error = -EINVAL;
- if (length < 0) /* sorry, but loff_t says... */
- goto out;
-
-- error = user_path_walk(path, &nd);
-+ error = user_path_walk_it(path, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -144,6 +149,7 @@
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -235,8 +241,9 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -262,6 +270,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -279,8 +288,9 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
-
- if (error)
- goto out;
-@@ -306,6 +317,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -322,6 +334,7 @@
- int old_fsuid, old_fsgid;
- kernel_cap_t old_cap;
- int res;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
- return -EINVAL;
-@@ -339,13 +352,14 @@
- else
- current->cap_effective = current->cap_permitted;
-
-- res = user_path_walk(filename, &nd);
-+ res = user_path_walk_it(filename, &nd, &it);
- if (!res) {
- res = permission(nd.dentry->d_inode, mode);
- /* SuS v2 requires we report a read only fs too */
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
- && !special_file(nd.dentry->d_inode->i_mode))
- res = -EROFS;
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
-
-@@ -361,6 +375,7 @@
- int error;
- struct nameidata nd;
- char *name;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- name = getname(filename);
- error = PTR_ERR(name);
-@@ -369,7 +384,7 @@
-
- error = 0;
- if (path_init(name,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd))
-- error = path_walk(name, &nd);
-+ error = path_walk_it(name, &nd, &it);
- putname(name);
- if (error)
- goto out;
-@@ -381,6 +397,7 @@
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -421,6 +438,7 @@
- int error;
- struct nameidata nd;
- char *name;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- name = getname(filename);
- error = PTR_ERR(name);
-@@ -429,7 +447,7 @@
-
- path_init(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
-- error = path_walk(name, &nd);
-+ error = path_walk_it(name, &nd, &it);
- putname(name);
- if (error)
- goto out;
-@@ -446,6 +465,7 @@
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -490,8 +510,9 @@
- struct inode * inode;
- int error;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -511,6 +532,7 @@
- error = notify_change(nd.dentry, &newattrs);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -580,10 +602,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -593,10 +618,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -630,10 +658,16 @@
- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
- * used by symlinks.
- */
-+extern int open_namei_it(const char *filename, int namei_flags, int mode,
-+ struct nameidata *nd, struct lookup_intent *it);
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
-+
- struct file *filp_open(const char * filename, int flags, int mode)
- {
- int namei_flags, error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -641,14 +675,15 @@
- if (namei_flags & O_TRUNC)
- namei_flags |= 2;
-
-- error = open_namei(filename, namei_flags, mode, &nd);
-- if (!error)
-- return dentry_open(nd.dentry, nd.mnt, flags);
-+ error = open_namei_it(filename, namei_flags, mode, &nd, &it);
-+ if (error)
-+ return ERR_PTR(error);
-
-- return ERR_PTR(error);
-+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
- }
-
--struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it)
- {
- struct file * f;
- struct inode *inode;
-@@ -691,6 +726,7 @@
- }
- f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
-
-+ intent_release(dentry, it);
- return f;
-
- cleanup_all:
-@@ -705,11 +741,17 @@
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(dentry, it);
- dput(dentry);
- mntput(mnt);
- return ERR_PTR(error);
- }
-
-+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+{
-+ return dentry_open_it(dentry, mnt, flags, NULL);
-+}
-+
- /*
- * Find an empty file descriptor entry, and mark it busy.
- */
---- lum-pristine/fs/stat.c Thu Sep 13 19:04:43 2001
-+++ lum/fs/stat.c Mon Aug 12 00:04:39 2002
-@@ -13,6 +13,7 @@
-
- #include <asm/uaccess.h>
-
-+extern void intent_release(struct dentry *de, struct lookup_intent *it);
- /*
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
-@@ -135,13 +135,15 @@
- asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_old_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -151,13 +153,15 @@
- asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_new_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -172,13 +176,15 @@
- asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_old_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -189,13 +195,15 @@
- asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
- int error;
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_new_stat(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -247,20 +255,21 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_READLINK };
-
- if (bufsiz <= 0)
- return -EINVAL;
-
-- error = user_path_walk_link(path, &nd);
-+ error = user_path_walk_link_it(path, &nd, &it);
- if (!error) {
- struct inode * inode = nd.dentry->d_inode;
--
- error = -EINVAL;
- if (inode->i_op && inode->i_op->readlink &&
- !(error = do_revalidate(nd.dentry))) {
- UPDATE_ATIME(inode);
- error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
- }
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -333,12 +342,14 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -348,12 +359,14 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
- error = do_revalidate(nd.dentry);
- if (!error)
- error = cp_new_stat64(nd.dentry->d_inode, statbuf);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
---- lum-pristine/mm/slab.c Fri Dec 21 12:42:05 2001
-+++ lum/mm/slab.c Thu Aug 1 18:07:35 2002
-@@ -1187,6 +1187,59 @@
- * Called with the cache-lock held.
- */
-
-+extern struct page *check_get_page(unsigned long kaddr);
-+struct page *page_mem_map(struct page *page);
-+static int kmem_check_cache_obj (kmem_cache_t * cachep,
-+ slab_t *slabp, void * objp)
-+{
-+ int i;
-+ unsigned int objnr;
-+
-+#if DEBUG
-+ if (cachep->flags & SLAB_RED_ZONE) {
-+ objp -= BYTES_PER_WORD;
-+ if ( *(unsigned long *)objp != RED_MAGIC2)
-+ /* Either write before start, or a double free. */
-+ return 0;
-+ if (*(unsigned long *)(objp+cachep->objsize -
-+ BYTES_PER_WORD) != RED_MAGIC2)
-+ /* Either write past end, or a double free. */
-+ return 0;
-+ }
-+#endif
-+
-+ objnr = (objp-slabp->s_mem)/cachep->objsize;
-+ if (objnr >= cachep->num)
-+ return 0;
-+ if (objp != slabp->s_mem + objnr*cachep->objsize)
-+ return 0;
-+
-+ /* Check slab's freelist to see if this obj is there. */
-+ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
-+ if (i == objnr)
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ struct page *page = check_get_page((unsigned long)objp);
-+
-+ if (!VALID_PAGE(page))
-+ return 0;
-+
-+ if (!PageSlab(page))
-+ return 0;
-+
-+ /* XXX check for freed slab objects ? */
-+ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
-+ return 0;
-+
-+ return (cachep == GET_PAGE_CACHE(page));
-+}
-+
- #if DEBUG
- static int kmem_extra_free_checks (kmem_cache_t * cachep,
- slab_t *slabp, void * objp)
+++ /dev/null
---- linux-2.4.18-17.8.0-uml-pristine/include/linux/lustre_version.h Wed Dec 31 19:00:00 1969
-+++ linux-2.4.18-17.8.0-uml/include/linux/lustre_version.h Tue Nov 26 07:02:14 2002
-@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 3
---- linux-2.4.18-17.8.0-uml-pristine/arch/ia64/mm/init.c 2002-10-19 11:44:08.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/arch/ia64/mm/init.c 2002-10-19 11:44:51.000000000 -0600
-@@ -37,6 +37,12 @@
-
- static unsigned long totalram_pages;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int
- do_check_pgt_cache (int low, int high)
- {
---- linux-2.4.18-17.8.0-uml-pristine/arch/i386/mm/init.c 2002-10-19 11:44:04.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/arch/i386/mm/init.c 2002-10-19 11:44:51.000000000 -0600
-@@ -43,6 +43,12 @@
- static unsigned long totalram_pages;
- static unsigned long totalhigh_pages;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int do_check_pgt_cache(int low, int high)
- {
- int freed = 0;
---- linux-2.4.18-17.8.0-uml-pristine/drivers/block/blkpg.c 2002-10-19 11:43:55.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/drivers/block/blkpg.c 2002-10-19 11:44:51.000000000 -0600
-@@ -297,3 +297,38 @@
- }
-
- EXPORT_SYMBOL(blk_ioctl);
-+
-+#define NUM_DEV_NO_WRITE 16
-+static int dev_no_write[NUM_DEV_NO_WRITE];
-+
-+/*
-+ * Debug code for turning block devices "read-only" (will discard writes
-+ * silently). This is for filesystem crash/recovery testing.
-+ */
-+void dev_set_rdonly(kdev_t dev, int no_write)
-+{
-+ if (dev) {
-+ printk(KERN_WARNING "Turning device %s read-only\n",
-+ bdevname(dev));
-+ dev_no_write[no_write] = 0xdead0000 + dev;
-+ }
-+}
-+
-+int dev_check_rdonly(kdev_t dev) {
-+ int i;
-+
-+ for (i = 0; i < NUM_DEV_NO_WRITE; i++) {
-+ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 &&
-+ dev == (dev_no_write[i] & 0xffff))
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+void dev_clear_rdonly(int no_write) {
-+ dev_no_write[no_write] = 0;
-+}
-+
-+EXPORT_SYMBOL(dev_set_rdonly);
-+EXPORT_SYMBOL(dev_check_rdonly);
-+EXPORT_SYMBOL(dev_clear_rdonly);
---- linux-2.4.18-17.8.0-uml-pristine/drivers/block/loop.c 2002-10-19 11:43:55.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/drivers/block/loop.c 2002-10-19 11:44:51.000000000 -0600
-@@ -491,6 +491,11 @@
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (dev_check_rdonly(rbh->b_rdev))
-+ goto err;
-+#endif
-+
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
---- linux-2.4.18-17.8.0-uml-pristine/drivers/ide/ide-disk.c 2002-10-19 11:43:58.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/drivers/ide/ide-disk.c 2002-10-19 11:44:51.000000000 -0600
-@@ -557,6 +557,12 @@
- */
- static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
- {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
-+ ide_end_request(1, HWGROUP(drive));
-+ return ide_stopped;
-+ }
-+#endif
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
-
---- linux-2.4.18-17.8.0-uml-pristine/fs/ext3/Makefile 2002-10-19 11:43:53.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/fs/ext3/Makefile 2002-10-19 11:44:51.000000000 -0600
-@@ -9,6 +9,8 @@
-
- O_TARGET := ext3.o
-
-+export-objs := super.o
-+
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
---- linux-2.4.18-17.8.0-uml-pristine/fs/ext3/super.c 2002-10-19 11:43:53.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/fs/ext3/super.c 2002-10-19 11:44:51.000000000 -0600
-@@ -1746,7 +1746,7 @@
- unregister_filesystem(&ext3_fs_type);
- }
-
--EXPORT_NO_SYMBOLS;
-+EXPORT_SYMBOL(ext3_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
- MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
---- linux-2.4.18-17.8.0-uml-pristine/include/linux/slab.h 2002-10-19 11:43:54.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/include/linux/slab.h 2002-11-02 00:49:24.000000000 -0700
-@@ -57,6 +57,7 @@
- extern int kmem_cache_shrink(kmem_cache_t *);
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
-
- extern void *kmalloc(size_t, int);
- extern void kfree(const void *);
---- linux-2.4.18-17.8.0-uml-pristine/kernel/ksyms.c 2002-10-19 11:43:53.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/kernel/ksyms.c 2002-11-02 01:09:34.000000000 -0700
-@@ -292,6 +292,7 @@
- EXPORT_SYMBOL(set_page_dirty);
- EXPORT_SYMBOL(vfs_readlink);
- EXPORT_SYMBOL(vfs_follow_link);
-+EXPORT_SYMBOL(vfs_follow_link_it);
- EXPORT_SYMBOL(page_readlink);
- EXPORT_SYMBOL(page_follow_link);
- EXPORT_SYMBOL(page_symlink_inode_operations);
-@@ -306,6 +307,12 @@
- EXPORT_SYMBOL_GPL(nr_free_pages);
- EXPORT_SYMBOL_GPL(page_cache_size);
-
-+/* lustre */
-+EXPORT_SYMBOL(panic_notifier_list);
-+EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(do_kern_mount);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+
- /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
- EXPORT_SYMBOL(default_llseek);
- EXPORT_SYMBOL(dentry_open);
---- linux-2.4.18-17.8.0-uml-pristine/include/linux/dcache.h 2002-10-19 11:43:54.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/include/linux/dcache.h 2002-11-02 00:49:24.000000000 -0700
-@@ -6,6 +6,34 @@
- #include <asm/atomic.h>
- #include <linux/mount.h>
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_LINK2 (1<<4)
-+#define IT_SYMLINK (1<<5)
-+#define IT_UNLINK (1<<6)
-+#define IT_RMDIR (1<<7)
-+#define IT_RENAME (1<<8)
-+#define IT_RENAME2 (1<<9)
-+#define IT_READDIR (1<<10)
-+#define IT_GETATTR (1<<11)
-+#define IT_SETATTR (1<<12)
-+#define IT_READLINK (1<<13)
-+#define IT_MKNOD (1<<14)
-+#define IT_LOOKUP (1<<15)
-+
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -78,6 +106,7 @@
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
- struct super_block * d_sb; /* The root of the dentry tree */
-+ struct lookup_intent *d_it;
- unsigned long d_vfs_flags;
- void * d_fsdata; /* fs-specific data */
- void * d_extra_attributes; /* TUX-specific data */
-@@ -91,6 +120,8 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *, struct lookup_intent *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
---- linux-2.4.18-17.8.0-uml-pristine/include/linux/fs.h 2002-10-19 11:43:54.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/include/linux/fs.h 2002-11-02 00:49:24.000000000 -0700
-@@ -576,6 +576,7 @@
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_intent;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -836,7 +837,9 @@
- extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
- extern int vfs_rmdir(struct inode *, struct dentry *);
- extern int vfs_unlink(struct inode *, struct dentry *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it);
-
- /*
- * File types
-@@ -897,6 +900,7 @@
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -907,6 +911,8 @@
- struct inode *, struct dentry *);
- int (*readlink) (struct dentry *, char *,int);
- int (*follow_link) (struct dentry *, struct nameidata *);
-+ int (*follow_link2) (struct dentry *, struct nameidata *,
-+ struct lookup_intent *it);
- void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
- int (*revalidate) (struct dentry *);
-@@ -1046,6 +1052,7 @@
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
-+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
- extern void umount_tree(struct vfsmount *);
-
- #define kern_umount mntput
-@@ -1380,6 +1387,7 @@
- extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
-
- extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
-+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
- extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
- extern int FASTCALL(path_walk(const char *, struct nameidata *));
- extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1391,6 +1399,8 @@
- extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
- #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
- #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
-+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
-+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
-
- extern void inode_init_once(struct inode *);
- extern void iput(struct inode *);
-@@ -1491,6 +1501,8 @@
-
- extern int vfs_readlink(struct dentry *, char *, int, const char *);
- extern int vfs_follow_link(struct nameidata *, const char *);
-+extern int vfs_follow_link_it(struct nameidata *, const char *,
-+ struct lookup_intent *it);
- extern int page_readlink(struct dentry *, char *, int);
- extern int page_follow_link(struct dentry *, struct nameidata *);
- extern struct inode_operations page_symlink_inode_operations;
---- linux-2.4.18-17.8.0-uml-pristine/fs/dcache.c 2002-10-19 11:43:53.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/fs/dcache.c 2002-10-31 13:10:34.000000000 -0700
-@@ -150,6 +150,8 @@
- unhash_it:
- list_del_init(&dentry->d_hash);
-
-+
-+
- kill_it: {
- struct dentry *parent;
- list_del(&dentry->d_child);
-@@ -645,6 +647,7 @@
- dentry->d_fsdata = NULL;
- dentry->d_extra_attributes = NULL;
- dentry->d_mounted = 0;
-+ dentry->d_it = NULL;
- INIT_LIST_HEAD(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_subdirs);
---- linux-2.4.18-17.8.0-uml-pristine/fs/nfsd/vfs.c 2002-10-19 11:43:53.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/fs/nfsd/vfs.c 2002-10-19 11:44:51.000000000 -0600
-@@ -1298,7 +1298,7 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- unlock_kernel();
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
---- linux-2.4.18-17.8.0-uml-pristine/fs/namei.c 2002-10-19 11:43:53.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/fs/namei.c 2002-11-02 01:02:26.000000000 -0700
-@@ -1,3 +1,6 @@
-+
-+
-+
- /*
- * linux/fs/namei.c
- *
-@@ -94,6 +97,14 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct dentry *de, struct lookup_intent *it)
-+{
-+ if (de->d_op && de->d_op->d_intent_release)
-+ de->d_op->d_intent_release(de, it);
-+
-+}
-+
-+
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
-@@ -260,10 +271,19 @@
- * Internal lookup() using the new generic dcache.
- * SMP-safe
- */
--static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * dentry = d_lookup(parent, name);
-
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -281,7 +301,8 @@
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
--static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * result;
- struct inode *dir = parent->d_inode;
-@@ -300,6 +321,9 @@
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- lock_kernel();
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -321,6 +345,12 @@
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
- }
- return result;
- }
-@@ -334,7 +364,8 @@
- * Without that kind of total limit, nasty chains of consecutive
- * symlinks can cause almost arbitrarily long lookups.
- */
--static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
-+static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- int err;
- if (current->link_count >= max_recursive_link)
-@@ -348,10 +379,14 @@
- current->link_count++;
- current->total_link_count++;
- UPDATE_ATIME(dentry->d_inode);
-- err = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ err = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ err = dentry->d_inode->i_op->follow_link(dentry, nd);
- current->link_count--;
- return err;
- loop:
-+ intent_release(dentry, it);
- path_release(nd);
- return -ELOOP;
- }
-@@ -449,7 +484,8 @@
- *
- * We expect 'base' to be positive and a directory.
- */
--int link_path_walk(const char * name, struct nameidata *nd)
-+int link_path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
- struct inode *inode;
-@@ -526,12 +562,12 @@
- break;
- }
- /* This does the actual lookups.. */
-- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
- if (!dentry) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -548,8 +584,8 @@
- if (!inode->i_op)
- goto out_dput;
-
-- if (inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ if (inode->i_op->follow_link || inode->i_op->follow_link2) {
-+ err = do_follow_link(dentry, nd, it);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -565,7 +601,7 @@
- nd->dentry = dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -592,12 +628,12 @@
- if (err < 0)
- break;
- }
-- dentry = cached_lookup(nd->dentry, &this, 0);
-+ dentry = cached_lookup(nd->dentry, &this, 0, it);
- if (!dentry) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- dentry = real_lookup(nd->dentry, &this, 0);
-+ dentry = real_lookup(nd->dentry, &this, 0, it);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -606,8 +642,10 @@
- ;
- inode = dentry->d_inode;
- if ((lookup_flags & LOOKUP_FOLLOW)
-- && inode && inode->i_op && inode->i_op->follow_link) {
-- err = do_follow_link(dentry, nd);
-+ && inode && inode->i_op &&
-+ (inode->i_op->follow_link ||
-+ inode->i_op->follow_link2)) {
-+ err = do_follow_link(dentry, nd, it);
- dput(dentry);
- if (err)
- goto return_err;
-@@ -621,7 +659,8 @@
- goto no_inode;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op || (!inode->i_op->lookup &&
-+ !inode->i_op->lookup2))
- break;
- }
- goto return_base;
-@@ -663,10 +702,21 @@
- return err;
- }
-
-+int link_path_walk(const char * name, struct nameidata *nd)
-+{
-+ return link_path_walk_it(name, nd, NULL);
-+}
-+
-+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
-+{
-+ current->total_link_count = 0;
-+ return link_path_walk_it(name, nd, it);
-+}
-+
- int path_walk(const char * name, struct nameidata *nd)
- {
- current->total_link_count = 0;
-- return link_path_walk(name, nd);
-+ return link_path_walk_it(name, nd, NULL);
- }
-
- /* SMP-safe */
-@@ -751,6 +801,17 @@
- }
-
- /* SMP-safe */
-+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ int error = 0;
-+ if (path_init(path, flags, nd))
-+ error = path_walk_it(path, nd, it);
-+ return error;
-+}
-+
-+
-+/* SMP-safe */
- int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
- {
- int error = 0;
-@@ -779,7 +840,8 @@
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -802,13 +864,16 @@
- goto out;
- }
-
-- dentry = cached_lookup(base, name, 0);
-+ dentry = cached_lookup(base, name, 0, it);
- if (!dentry) {
- struct dentry *new = d_alloc(base, name);
- dentry = ERR_PTR(-ENOMEM);
- if (!new)
- goto out;
- lock_kernel();
-+ if (inode->i_op->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -820,6 +885,12 @@
- return dentry;
- }
-
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+{
-+ return lookup_hash_it(name, base, NULL);
-+}
-+
-+
- /* SMP-safe */
- struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
- {
-@@ -841,7 +912,7 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash_it(&this, base, NULL);
- access:
- return ERR_PTR(-EACCES);
- }
-@@ -872,6 +943,23 @@
- return err;
- }
-
-+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ char *tmp;
-+ int err;
-+
-+ tmp = getname(name);
-+ err = PTR_ERR(tmp);
-+ if (!IS_ERR(tmp)) {
-+ err = 0;
-+ if (path_init(tmp, flags, nd))
-+ err = path_walk_it(tmp, nd, it);
-+ putname(tmp);
-+ }
-+ return err;
-+}
-+
- /*
- * It's inline, so penalty for filesystems that don't use sticky bit is
- * minimal.
-@@ -1010,7 +1098,8 @@
- * for symlinks (where the permissions are checked later).
- * SMP-safe
- */
--int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
-+int open_namei_it(const char *pathname, int flag, int mode,
-+ struct nameidata *nd, struct lookup_intent *it)
- {
- int acc_mode, error = 0;
- struct inode *inode;
-@@ -1024,7 +1113,7 @@
- * The simplest case - just a plain lookup.
- */
- if (!(flag & O_CREAT)) {
-- error = path_lookup(pathname, lookup_flags(flag), nd);
-+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it);
- if (error)
- return error;
- dentry = nd->dentry;
-@@ -1034,6 +1123,10 @@
- /*
- * Create - we need to know the parent.
- */
-+ if (it) {
-+ it->it_mode = mode;
-+ it->it_op |= IT_CREAT;
-+ }
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
- if (error)
- return error;
-@@ -1049,7 +1142,7 @@
-
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1058,6 +1151,7 @@
- goto exit;
- }
-
-+ it->it_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
- error = vfs_create(dir->d_inode, dentry,
-@@ -1091,7 +1185,8 @@
- error = -ENOENT;
- if (!dentry->d_inode)
- goto exit_dput;
-- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
-+ if (dentry->d_inode->i_op && (dentry->d_inode->i_op->follow_link ||
-+ dentry->d_inode->i_op->follow_link2))
- goto do_link;
-
- dput(nd->dentry);
-@@ -1177,8 +1272,10 @@
- return 0;
-
- exit_dput:
-+ intent_release(dentry, it);
- dput(dentry);
- exit:
-+ intent_release(nd->dentry, it);
- path_release(nd);
- return error;
-
-@@ -1197,7 +1294,12 @@
- * are done. Procfs-like symlinks just set LAST_BIND.
- */
- UPDATE_ATIME(dentry->d_inode);
-- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (dentry->d_inode->i_op->follow_link2)
-+ error = dentry->d_inode->i_op->follow_link2(dentry, nd, it);
-+ else
-+ error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(dentry, it);
- dput(dentry);
- if (error)
- return error;
-@@ -1219,13 +1321,20 @@
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
- putname(nd->last.name);
- goto do_last;
- }
-
-+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd)
-+{
-+ return open_namei_it(pathname, flag, mode, nd, NULL);
-+}
-+
-+
- /* SMP-safe */
--static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
-+static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
-
-@@ -1233,7 +1342,7 @@
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1279,6 +1388,7 @@
- char * tmp;
- struct dentry * dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode };
-
- if (S_ISDIR(mode))
- return -EPERM;
-@@ -1289,7 +1399,7 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
-
- mode &= ~current->fs->umask;
-@@ -1307,6 +1417,7 @@
- default:
- error = -EINVAL;
- }
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1347,6 +1458,7 @@
- {
- int error = 0;
- char * tmp;
-+ struct lookup_intent it = { .it_op = IT_MKDIR, .it_mode = mode };
-
- tmp = getname(pathname);
- error = PTR_ERR(tmp);
-@@ -1357,11 +1469,12 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 1);
-+ dentry = lookup_create(&nd, 1, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_mkdir(nd.dentry->d_inode, dentry,
- mode & ~current->fs->umask);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1445,6 +1558,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_RMDIR };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1466,10 +1580,11 @@
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1513,6 +1628,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_UNLINK };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1525,7 +1641,7 @@
- if (nd.last_type != LAST_NORM)
- goto exit1;
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1533,6 +1649,7 @@
- goto slashes;
- error = vfs_unlink(nd.dentry->d_inode, dentry);
- exit2:
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1579,6 +1696,7 @@
- int error = 0;
- char * from;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_SYMLINK };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1592,10 +1710,12 @@
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ it.it_data = from;
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1660,6 +1780,7 @@
- {
- int error;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_LINK };
-
- to = getname(newname);
- error = PTR_ERR(to);
-@@ -1667,7 +1788,7 @@
- struct dentry *new_dentry;
- struct nameidata nd, old_nd;
-
-- error = __user_walk(oldname, LOOKUP_POSITIVE, &old_nd);
-+ error = __user_walk_it(oldname, LOOKUP_POSITIVE, &old_nd, &it);
- if (error)
- goto exit;
- error = path_lookup(to, LOOKUP_PARENT, &nd);
-@@ -1676,10 +1797,12 @@
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-- new_dentry = lookup_create(&nd, 0);
-+ it.it_op = IT_LINK2;
-+ new_dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-+ intent_release(new_dentry, &it);
- dput(new_dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1720,7 +1843,8 @@
- * locking].
- */
- int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- struct inode *target;
-@@ -1778,6 +1902,7 @@
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- if (target) {
- if (!error)
- target->i_flags |= S_DEAD;
-@@ -1799,7 +1924,8 @@
- }
-
- int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -1830,6 +1956,7 @@
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- double_up(&old_dir->i_zombie, &new_dir->i_zombie);
- if (error)
- return error;
-@@ -1841,13 +1968,14 @@
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- if (S_ISDIR(old_dentry->d_inode->i_mode))
-- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
- else
-- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
- if (!error) {
- if (old_dir == new_dir)
- inode_dir_notify(old_dir, DN_RENAME);
-@@ -1864,6 +1992,7 @@
- int error = 0;
- struct dentry * old_dir, * new_dir;
- struct dentry * old_dentry, *new_dentry;
-+ struct lookup_intent it = { .it_op = IT_RENAME };
- struct nameidata oldnd, newnd;
-
- error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
-@@ -1889,7 +2018,7 @@
-
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -1905,18 +2034,21 @@
- if (newnd.last.name[newnd.last.len])
- goto exit4;
- }
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ it.it_op = IT_RENAME2;
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, &it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-
- lock_kernel();
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, &it);
- unlock_kernel();
-
-+ intent_release(new_dentry, NULL);
- dput(new_dentry);
- exit4:
-+ intent_release(old_dentry, &it);
- dput(old_dentry);
- exit3:
- double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
-@@ -1965,7 +2097,8 @@
- }
-
- static inline int
--__vfs_follow_link(struct nameidata *nd, const char *link)
-+__vfs_follow_link(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
- {
- int res = 0;
- char *name;
-@@ -1978,7 +2111,7 @@
- /* weird __emul_prefix() stuff did it */
- goto out;
- }
-- res = link_path_walk(link, nd);
-+ res = link_path_walk_it(link, nd, it);
- out:
- if (current->link_count || res || nd->last_type!=LAST_NORM)
- return res;
-@@ -2000,7 +2133,13 @@
-
- int vfs_follow_link(struct nameidata *nd, const char *link)
- {
-- return __vfs_follow_link(nd, link);
-+ return __vfs_follow_link(nd, link, NULL);
-+}
-+
-+int vfs_follow_link_it(struct nameidata *nd, const char *link,
-+ struct lookup_intent *it)
-+{
-+ return __vfs_follow_link(nd, link, it);
- }
-
- /* get the link contents into pagecache */
-@@ -2042,7 +2181,7 @@
- {
- struct page *page = NULL;
- char *s = page_getlink(dentry, &page);
-- int res = __vfs_follow_link(nd, s);
-+ int res = __vfs_follow_link(nd, s, NULL);
- if (page) {
- kunmap(page);
- page_cache_release(page);
---- linux-2.4.18-17.8.0-uml-pristine/fs/open.c 2002-10-19 11:43:53.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/fs/open.c 2002-10-19 11:44:51.000000000 -0600
-@@ -19,6 +19,9 @@
- #include <asm/uaccess.h>
-
- #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
-+extern int path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it);
-+extern void intent_release(struct dentry *de, struct lookup_intent *it);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -118,12 +121,13 @@
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
- error = -EINVAL;
- if (length < 0) /* sorry, but loff_t says... */
- goto out;
-
-- error = user_path_walk(path, &nd);
-+ error = user_path_walk_it(path, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -168,6 +172,7 @@
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -259,8 +264,9 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -286,6 +292,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -303,8 +310,9 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
-
- if (error)
- goto out;
-@@ -331,6 +339,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -347,6 +356,7 @@
- int old_fsuid, old_fsgid;
- kernel_cap_t old_cap;
- int res;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
- return -EINVAL;
-@@ -364,13 +374,14 @@
- else
- current->cap_effective = current->cap_permitted;
-
-- res = user_path_walk(filename, &nd);
-+ res = user_path_walk_it(filename, &nd, &it);
- if (!res) {
- res = permission(nd.dentry->d_inode, mode);
- /* SuS v2 requires we report a read only fs too */
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
- && !special_file(nd.dentry->d_inode->i_mode))
- res = -EROFS;
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
-
-@@ -385,8 +396,11 @@
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
-+ error = __user_walk_it(filename,
-+ LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,
-+ &nd, &it);
- if (error)
- goto out;
-
-@@ -397,6 +411,7 @@
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -436,9 +451,10 @@
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
-- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
-+ error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
-+ LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it);
- if (error)
- goto out;
-
-@@ -454,6 +470,7 @@
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -498,8 +515,9 @@
- struct inode * inode;
- int error;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -519,6 +537,7 @@
- error = notify_change(nd.dentry, &newattrs);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -588,10 +607,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -601,10 +622,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -638,10 +661,16 @@
- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
- * used by symlinks.
- */
-+extern int open_namei_it(const char *filename, int namei_flags, int mode,
-+ struct nameidata *nd, struct lookup_intent *it);
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
-+
- struct file *filp_open(const char * filename, int flags, int mode)
- {
- int namei_flags, error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -649,18 +678,19 @@
- if (namei_flags & O_TRUNC)
- namei_flags |= 2;
-
-- error = open_namei(filename, namei_flags, mode, &nd);
-- if (!error)
-- return dentry_open(nd.dentry, nd.mnt, flags);
-+ error = open_namei_it(filename, namei_flags, mode, &nd, &it);
-+ if (error)
-+ return ERR_PTR(error);
-
-- return ERR_PTR(error);
-+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
- }
-
- extern ssize_t do_readahead(struct file *file, unsigned long index, unsigned long nr);
- /* for files over a certains size it doesn't pay to do readahead on open */
- #define READAHEAD_CUTOFF 48000
-
--struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it)
- {
- struct file * f;
- struct inode *inode;
-@@ -711,6 +741,7 @@
- do_readahead(f, 0, (48 * 1024) >> PAGE_SHIFT);
-
-
-+ intent_release(dentry, it);
- return f;
-
- cleanup_all:
-@@ -725,11 +756,17 @@
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(dentry, it);
- dput(dentry);
- mntput(mnt);
- return ERR_PTR(error);
- }
-
-+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+{
-+ return dentry_open_it(dentry, mnt, flags, NULL);
-+}
-+
- /*
- * Find an empty file descriptor entry, and mark it busy.
- */
---- linux-2.4.18-17.8.0-uml-pristine/fs/stat.c 2002-10-19 11:43:53.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/fs/stat.c 2002-10-19 11:44:51.000000000 -0600
-@@ -13,6 +13,7 @@
-
- #include <asm/uaccess.h>
-
-+extern void intent_release(struct dentry *de, struct lookup_intent *it);
- /*
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
-@@ -104,10 +105,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk(name, &nd);
-+ error = user_path_walk_it(name, &nd, &it);
- if (!error) {
- error = do_getattr(nd.mnt, nd.dentry, stat);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -117,10 +120,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk_link(name, &nd);
-+ error = user_path_walk_link_it(name, &nd, &it);
- if (!error) {
- error = do_getattr(nd.mnt, nd.dentry, stat);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
---- linux-2.4.18-17.8.0-uml-pristine/mm/slab.c 2002-10-19 11:43:54.000000000 -0600
-+++ linux-2.4.18-17.8.0-uml/mm/slab.c 2002-10-19 11:44:51.000000000 -0600
-@@ -1208,6 +1208,59 @@
- * Called with the cache-lock held.
- */
-
-+extern struct page *check_get_page(unsigned long kaddr);
-+struct page *page_mem_map(struct page *page);
-+static int kmem_check_cache_obj (kmem_cache_t * cachep,
-+ slab_t *slabp, void * objp)
-+{
-+ int i;
-+ unsigned int objnr;
-+
-+#if DEBUG
-+ if (cachep->flags & SLAB_RED_ZONE) {
-+ objp -= BYTES_PER_WORD;
-+ if ( *(unsigned long *)objp != RED_MAGIC2)
-+ /* Either write before start, or a double free. */
-+ return 0;
-+ if (*(unsigned long *)(objp+cachep->objsize -
-+ BYTES_PER_WORD) != RED_MAGIC2)
-+ /* Either write past end, or a double free. */
-+ return 0;
-+ }
-+#endif
-+
-+ objnr = (objp-slabp->s_mem)/cachep->objsize;
-+ if (objnr >= cachep->num)
-+ return 0;
-+ if (objp != slabp->s_mem + objnr*cachep->objsize)
-+ return 0;
-+
-+ /* Check slab's freelist to see if this obj is there. */
-+ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
-+ if (i == objnr)
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ struct page *page = check_get_page((unsigned long)objp);
-+
-+ if (!VALID_PAGE(page))
-+ return 0;
-+
-+ if (!PageSlab(page))
-+ return 0;
-+
-+ /* XXX check for freed slab objects ? */
-+ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
-+ return 0;
-+
-+ return (cachep == GET_PAGE_CACHE(page));
-+}
-+
- #if DEBUG
- static int kmem_extra_free_checks (kmem_cache_t * cachep,
- slab_t *slabp, void * objp)
+++ /dev/null
-diff -ruN linux/arch/alpha/mm/init.c linux-2.4.18-lustre/arch/alpha/mm/init.c
---- linux/arch/alpha/mm/init.c Thu Sep 20 21:02:03 2001
-+++ linux-2.4.18-lustre/arch/alpha/mm/init.c Tue Aug 6 12:37:55 2002
-@@ -46,6 +46,12 @@
- struct pgtable_cache_struct quicklists;
- #endif
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- pgd_t *
- get_pgd_slow(void)
- {
+++ /dev/null
---- linux-2.4.18-lustre12-pristine/arch/ia64/mm/init.c Wed Jun 26 00:15:21 2002
-+++ linux-2.4.18-lustre12/arch/ia64/mm/init.c Tue Aug 13 11:13:09 2002
-@@ -37,6 +37,12 @@
-
- static unsigned long totalram_pages;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int
- do_check_pgt_cache (int low, int high)
- {
---- linux-2.4.18-lustre12-pristine/arch/i386/mm/init.c Wed Jun 26 00:15:21 2002
-+++ linux-2.4.18-lustre12/arch/i386/mm/init.c Tue Aug 13 11:13:09 2002
-@@ -43,6 +43,12 @@
- static unsigned long totalram_pages;
- static unsigned long totalhigh_pages;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int do_check_pgt_cache(int low, int high)
- {
- int freed = 0;
---- linux-2.4.18-lustre12-pristine/drivers/block/blkpg.c Tue May 7 20:33:10 2002
-+++ linux-2.4.18-lustre12/drivers/block/blkpg.c Tue Aug 13 11:13:08 2002
-@@ -295,3 +295,38 @@
- }
-
- EXPORT_SYMBOL(blk_ioctl);
-+
-+#define NUM_DEV_NO_WRITE 16
-+static int dev_no_write[NUM_DEV_NO_WRITE];
-+
-+/*
-+ * Debug code for turning block devices "read-only" (will discard writes
-+ * silently). This is for filesystem crash/recovery testing.
-+ */
-+void dev_set_rdonly(kdev_t dev, int no_write)
-+{
-+ if (dev) {
-+ printk(KERN_WARNING "Turning device %s read-only\n",
-+ bdevname(dev));
-+ dev_no_write[no_write] = 0xdead0000 + dev;
-+ }
-+}
-+
-+int dev_check_rdonly(kdev_t dev) {
-+ int i;
-+
-+ for (i = 0; i < NUM_DEV_NO_WRITE; i++) {
-+ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 &&
-+ dev == (dev_no_write[i] & 0xffff))
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+void dev_clear_rdonly(int no_write) {
-+ dev_no_write[no_write] = 0;
-+}
-+
-+EXPORT_SYMBOL(dev_set_rdonly);
-+EXPORT_SYMBOL(dev_check_rdonly);
-+EXPORT_SYMBOL(dev_clear_rdonly);
---- linux-2.4.18-lustre12-pristine/drivers/block/loop.c Tue May 7 19:48:59 2002
-+++ linux-2.4.18-lustre12/drivers/block/loop.c Tue Aug 13 11:13:08 2002
-@@ -503,6 +503,11 @@
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (dev_check_rdonly(rbh->b_rdev))
-+ goto err;
-+#endif
-+
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
---- linux-2.4.18-lustre12-pristine/drivers/ide/ide-disk.c Tue May 7 18:43:35 2002
-+++ linux-2.4.18-lustre12/drivers/ide/ide-disk.c Tue Aug 13 11:13:08 2002
-@@ -557,6 +557,12 @@
- */
- static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
- {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
-+ ide_end_request(1, HWGROUP(drive));
-+ return ide_stopped;
-+ }
-+#endif
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
-
---- linux-2.4.18-lustre12-pristine/fs/ext3/Makefile Tue May 7 17:53:46 2002
-+++ linux-2.4.18-lustre12/fs/ext3/Makefile Tue Aug 13 11:13:08 2002
-@@ -9,6 +9,8 @@
-
- O_TARGET := ext3.o
-
-+export-objs := super.o
-+
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
---- linux-2.4.18-lustre12-pristine/fs/ext3/super.c Tue May 7 19:43:17 2002
-+++ linux-2.4.18-lustre12/fs/ext3/super.c Tue Aug 13 11:13:08 2002
-@@ -1746,7 +1746,7 @@
- unregister_filesystem(&ext3_fs_type);
- }
-
--EXPORT_NO_SYMBOLS;
-+EXPORT_SYMBOL(ext3_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
- MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
---- linux-2.4.18-lustre12-pristine/fs/jbd/commit.c Tue May 7 18:39:35 2002
-+++ linux-2.4.18-lustre12/fs/jbd/commit.c Tue Aug 13 11:13:08 2002
-@@ -482,7 +482,7 @@
- transaction's t_log_list queue, and metadata buffers are on
- the t_iobuf_list queue.
-
-- Wait for the transactions in reverse order. That way we are
-+ Wait for the buffers in reverse order. That way we are
- less likely to be woken up until all IOs have completed, and
- so we incur less scheduling load.
- */
-@@ -575,8 +575,10 @@
-
- jbd_debug(3, "JBD: commit phase 6\n");
-
-- if (is_journal_aborted(journal))
-+ if (is_journal_aborted(journal)) {
-+ unlock_journal(journal);
- goto skip_commit;
-+ }
-
- /* Done it all: now write the commit record. We should have
- * cleaned up our previous buffers by now, so if we are in abort
-@@ -586,9 +588,10 @@
- descriptor = journal_get_descriptor_buffer(journal);
- if (!descriptor) {
- __journal_abort_hard(journal);
-+ unlock_journal(journal);
- goto skip_commit;
- }
--
-+
- /* AKPM: buglet - add `i' to tmp! */
- for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
- journal_header_t *tmp =
-@@ -609,7 +612,6 @@
- put_bh(bh); /* One for getblk() */
- journal_unlock_journal_head(descriptor);
- }
-- lock_journal(journal);
-
- /* End of a transaction! Finally, we can do checkpoint
- processing: any buffers committed as a result of this
-@@ -618,6 +620,25 @@
-
- skip_commit:
-
-+ /* Call any callbacks that had been registered for handles in this
-+ * transaction. It is up to the callback to free any allocated
-+ * memory.
-+ */
-+ if (!list_empty(&commit_transaction->t_jcb)) {
-+ struct list_head *p, *n;
-+ int error = is_journal_aborted(journal);
-+
-+ list_for_each_safe(p, n, &commit_transaction->t_jcb) {
-+ struct journal_callback *jcb;
-+
-+ jcb = list_entry(p, struct journal_callback, jcb_list);
-+ list_del(p);
-+ jcb->jcb_func(jcb, error);
-+ }
-+ }
-+
-+ lock_journal(journal);
-+
- jbd_debug(3, "JBD: commit phase 7\n");
-
- J_ASSERT(commit_transaction->t_sync_datalist == NULL);
---- linux-2.4.18-lustre12-pristine/fs/jbd/journal.c Wed Jun 26 00:16:17 2002
-+++ linux-2.4.18-lustre12/fs/jbd/journal.c Tue Aug 13 11:13:08 2002
-@@ -58,6 +58,7 @@
- #endif
- EXPORT_SYMBOL(journal_flush);
- EXPORT_SYMBOL(journal_revoke);
-+EXPORT_SYMBOL(journal_callback_set);
-
- EXPORT_SYMBOL(journal_init_dev);
- EXPORT_SYMBOL(journal_init_inode);
---- linux-2.4.18-lustre12-pristine/fs/jbd/transaction.c Tue Jun 18 15:53:27 2002
-+++ linux-2.4.18-lustre12/fs/jbd/transaction.c Tue Aug 13 11:13:08 2002
-@@ -57,6 +57,7 @@
- transaction->t_state = T_RUNNING;
- transaction->t_tid = journal->j_transaction_sequence++;
- transaction->t_expires = jiffies + journal->j_commit_interval;
-+ INIT_LIST_HEAD(&transaction->t_jcb);
-
- /* Set up the commit timer for the new transaction. */
- J_ASSERT (!journal->j_commit_timer_active);
-@@ -201,6 +202,20 @@
- return 0;
- }
-
-+/* Allocate a new handle. This should probably be in a slab... */
-+static handle_t *get_handle(int nblocks)
-+{
-+ handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+ if (!handle)
-+ return NULL;
-+ memset(handle, 0, sizeof (handle_t));
-+ handle->h_buffer_credits = nblocks;
-+ handle->h_ref = 1;
-+ INIT_LIST_HEAD(&handle->h_jcb);
-+
-+ return handle;
-+}
-+
- /*
- * Obtain a new handle.
- *
-@@ -227,14 +242,11 @@
- handle->h_ref++;
- return handle;
- }
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = get_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = start_this_handle(journal, handle);
-@@ -333,14 +345,11 @@
-
- if (is_journal_aborted(journal))
- return ERR_PTR(-EIO);
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = get_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = try_start_this_handle(journal, handle);
-@@ -1319,6 +1328,29 @@
- #endif
-
- /*
-+ * Register a callback function for this handle. The function will be
-+ * called when the transaction that this handle is part of has been
-+ * committed to disk with the original callback data struct and the
-+ * error status of the journal as parameters. There is no guarantee of
-+ * ordering between handles within a single transaction, nor between
-+ * callbacks registered on the same handle.
-+ *
-+ * The caller is responsible for allocating the journal_callback struct.
-+ * This is to allow the caller to add as much extra data to the callback
-+ * as needed, but reduce the overhead of multiple allocations. The caller
-+ * allocated struct must start with a struct journal_callback at offset 0,
-+ * and has the caller-specific data afterwards.
-+ */
-+void journal_callback_set(handle_t *handle, void (*func)(void *, int),
-+ void *cb_data)
-+{
-+ struct journal_callback *jcb = cb_data;
-+
-+ list_add(&jcb->jcb_list, &handle->h_jcb);
-+ jcb->jcb_func = func;
-+}
-+
-+/*
- * All done for a particular handle.
- *
- * There is not much action needed here. We just return any remaining
-@@ -1383,7 +1415,10 @@
- wake_up(&journal->j_wait_transaction_locked);
- }
-
-- /*
-+ /* Move callbacks from the handle to the transaction. */
-+ list_splice(&handle->h_jcb, &transaction->t_jcb);
-+
-+ /*
- * If the handle is marked SYNC, we need to set another commit
- * going! We also want to force a commit if the current
- * transaction is occupying too much of the log, or if the
---- linux-2.4.18-lustre12-pristine/include/linux/blkdev.h Wed Jun 26 00:16:30 2002
-+++ linux-2.4.18-lustre12/include/linux/blkdev.h Tue Aug 13 11:13:08 2002
-@@ -228,4 +228,8 @@
- return retval;
- }
-
-+#define CONFIG_DEV_RDONLY
-+void dev_set_rdonly(kdev_t, int);
-+int dev_check_rdonly(kdev_t);
-+void dev_clear_rdonly(int);
- #endif
---- linux-2.4.18-lustre12-pristine/include/linux/slab.h Wed Jun 26 00:16:34 2002
-+++ linux-2.4.18-lustre12/include/linux/slab.h Tue Aug 13 11:13:09 2002
-@@ -57,6 +57,7 @@
- extern int kmem_cache_shrink(kmem_cache_t *);
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
-
- extern void *kmalloc(size_t, int);
- extern void kfree(const void *);
---- linux-2.4.18-lustre12-pristine/include/linux/jbd.h Tue May 7 19:43:17 2002
-+++ linux-2.4.18-lustre12/include/linux/jbd.h Tue Aug 13 11:13:08 2002
-@@ -257,6 +257,13 @@
- return bh->b_private;
- }
-
-+#define HAVE_JOURNAL_CALLBACK_STATUS
-+struct journal_callback {
-+ struct list_head jcb_list;
-+ void (*jcb_func)(void *cb_data, int error);
-+ /* user data goes here */
-+};
-+
- struct jbd_revoke_table_s;
-
- /* The handle_t type represents a single atomic update being performed
-@@ -287,6 +294,12 @@
- operations */
- int h_err;
-
-+ /* List of application registered callbacks for this handle.
-+ * The function(s) will be called after the transaction that
-+ * this handle is part of has been committed to disk.
-+ */
-+ struct list_head h_jcb;
-+
- /* Flags */
- unsigned int h_sync: 1; /* sync-on-close */
- unsigned int h_jdata: 1; /* force data journaling */
-@@ -406,6 +419,10 @@
-
- /* How many handles used this transaction? */
- int t_handle_count;
-+
-+ /* List of registered callback functions for this transaction.
-+ * Called when the transaction is committed. */
-+ struct list_head t_jcb;
- };
-
-
-@@ -654,6 +671,8 @@
- extern int journal_try_to_free_buffers(journal_t *, struct page *, int);
- extern int journal_stop(handle_t *);
- extern int journal_flush (journal_t *);
-+extern void journal_callback_set(handle_t *handle, void (*fn)(void *, int),
-+ void *cb_data);
-
- extern void journal_lock_updates (journal_t *);
- extern void journal_unlock_updates (journal_t *);
---- linux-2.4.18-lustre12-pristine/kernel/ksyms.c Wed Jun 26 00:16:38 2002
-+++ linux-2.4.18-lustre12/kernel/ksyms.c Tue Aug 13 11:13:08 2002
-@@ -306,6 +306,12 @@
- EXPORT_SYMBOL(lock_may_write);
- EXPORT_SYMBOL(dcache_readdir);
-
-+/* lustre */
-+EXPORT_SYMBOL(panic_notifier_list);
-+EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(do_kern_mount);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+
- /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
- EXPORT_SYMBOL(default_llseek);
- EXPORT_SYMBOL(dentry_open);
---- linux-2.4.18-lustre12-pristine/include/linux/dcache.h Tue May 7 18:22:37 2002
-+++ linux-2.4.18-lustre12/include/linux/dcache.h Tue Aug 13 11:13:09 2002
-@@ -6,6 +6,33 @@
- #include <asm/atomic.h>
- #include <linux/mount.h>
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_SYMLINK (1<<4)
-+#define IT_UNLINK (1<<5)
-+#define IT_RMDIR (1<<6)
-+#define IT_RENAME (1<<7)
-+#define IT_RENAME2 (1<<8)
-+#define IT_READDIR (1<<9)
-+#define IT_GETATTR (1<<10)
-+#define IT_SETATTR (1<<11)
-+#define IT_READLINK (1<<12)
-+#define IT_MKNOD (1<<13)
-+#define IT_LOOKUP (1<<14)
-+
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -78,6 +105,7 @@
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
- struct super_block * d_sb; /* The root of the dentry tree */
-+ struct lookup_intent *d_it;
- unsigned long d_vfs_flags;
- void * d_fsdata; /* fs-specific data */
- void * d_extra_attributes; /* TUX-specific data */
-@@ -91,6 +119,8 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
---- linux-2.4.18-lustre12-pristine/include/linux/fs.h Wed Jun 26 00:16:31 2002
-+++ linux-2.4.18-lustre12/include/linux/fs.h Tue Aug 13 11:13:09 2002
-@@ -572,6 +572,7 @@
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_intent;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -829,7 +830,9 @@
- extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
- extern int vfs_rmdir(struct inode *, struct dentry *);
- extern int vfs_unlink(struct inode *, struct dentry *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it);
-
- /*
- * File types
-@@ -890,6 +893,7 @@
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -1036,6 +1040,7 @@
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
-+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
- extern void umount_tree(struct vfsmount *);
-
- #define kern_umount mntput
-@@ -1370,6 +1375,7 @@
- extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
-
- extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
-+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
- extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
- extern int FASTCALL(path_walk(const char *, struct nameidata *));
- extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1381,6 +1387,8 @@
- extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
- #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
- #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
-+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
-+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
-
- extern void iput(struct inode *);
- extern void force_delete(struct inode *);
---- linux-2.4.18-lustre12-pristine/fs/dcache.c Wed Jun 26 00:16:14 2002
-+++ linux-2.4.18-lustre12/fs/dcache.c Tue Aug 13 11:13:09 2002
-@@ -645,6 +645,7 @@
- dentry->d_fsdata = NULL;
- dentry->d_extra_attributes = NULL;
- dentry->d_mounted = 0;
-+ dentry->d_it = NULL;
- INIT_LIST_HEAD(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_subdirs);
---- linux-2.4.18-lustre12-pristine/fs/nfsd/vfs.c Wed Jun 26 00:16:24 2002
-+++ linux-2.4.18-lustre12/fs/nfsd/vfs.c Tue Aug 13 11:13:09 2002
-@@ -1298,7 +1298,7 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- unlock_kernel();
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
---- linux-2.4.18-lustre12-pristine/fs/namei.c Wed Jun 26 00:16:14 2002
-+++ linux-2.4.18-lustre12/fs/namei.c Tue Aug 13 11:18:48 2002
-@@ -94,6 +94,14 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct dentry *de)
-+{
-+ if (de->d_op && de->d_op->d_intent_release)
-+ de->d_op->d_intent_release(de);
-+ de->d_it = NULL;
-+}
-+
-+
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
-@@ -260,10 +268,19 @@
- * Internal lookup() using the new generic dcache.
- * SMP-safe
- */
--static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * dentry = d_lookup(parent, name);
-
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -281,7 +298,8 @@
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
--static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * result;
- struct inode *dir = parent->d_inode;
-@@ -300,6 +318,9 @@
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- lock_kernel();
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -321,6 +342,12 @@
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
- }
- return result;
- }
-@@ -447,7 +475,8 @@
- *
- * We expect 'base' to be positive and a directory.
- */
--int link_path_walk(const char * name, struct nameidata *nd)
-+int link_path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
- struct inode *inode;
-@@ -524,12 +553,12 @@
- break;
- }
- /* This does the actual lookups.. */
-- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
- if (!dentry) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -563,7 +592,7 @@
- nd->dentry = dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -590,12 +619,12 @@
- if (err < 0)
- break;
- }
-- dentry = cached_lookup(nd->dentry, &this, 0);
-+ dentry = cached_lookup(nd->dentry, &this, 0, it);
- if (!dentry) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- dentry = real_lookup(nd->dentry, &this, 0);
-+ dentry = real_lookup(nd->dentry, &this, 0, it);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -619,7 +648,8 @@
- goto no_inode;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op || (!inode->i_op->lookup &&
-+ !inode->i_op->lookup2))
- break;
- }
- goto return_base;
-@@ -651,6 +681,7 @@
- }
- }
- return_base:
-+ nd->dentry->d_it = it;
- return 0;
- out_dput:
- dput(dentry);
-@@ -658,15 +689,29 @@
- }
- path_release(nd);
- return_err:
-+ if (!err)
-+ nd->dentry->d_it = it;
- return err;
- }
-
-+int link_path_walk(const char * name, struct nameidata *nd)
-+{
-+ return link_path_walk_it(name, nd, NULL);
-+}
-+
-+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
-+{
-+ current->total_link_count = 0;
-+ return link_path_walk_it(name, nd, it);
-+}
-+
- int path_walk(const char * name, struct nameidata *nd)
- {
- current->total_link_count = 0;
-- return link_path_walk(name, nd);
-+ return link_path_walk_it(name, nd, NULL);
- }
-
-+
- /* SMP-safe */
- /* returns 1 if everything is done */
- static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
-@@ -749,6 +794,17 @@
- }
-
- /* SMP-safe */
-+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ int error = 0;
-+ if (path_init(path, flags, nd))
-+ error = path_walk_it(path, nd, it);
-+ return error;
-+}
-+
-+
-+/* SMP-safe */
- int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
- {
- int error = 0;
-@@ -777,7 +833,8 @@
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -800,13 +857,16 @@
- goto out;
- }
-
-- dentry = cached_lookup(base, name, 0);
-+ dentry = cached_lookup(base, name, 0, it);
- if (!dentry) {
- struct dentry *new = d_alloc(base, name);
- dentry = ERR_PTR(-ENOMEM);
- if (!new)
- goto out;
- lock_kernel();
-+ if (inode->i_op->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -818,6 +878,12 @@
- return dentry;
- }
-
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+{
-+ return lookup_hash_it(name, base, NULL);
-+}
-+
-+
- /* SMP-safe */
- struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
- {
-@@ -839,7 +905,7 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash_it(&this, base, NULL);
- access:
- return ERR_PTR(-EACCES);
- }
-@@ -870,6 +936,23 @@
- return err;
- }
-
-+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ char *tmp;
-+ int err;
-+
-+ tmp = getname(name);
-+ err = PTR_ERR(tmp);
-+ if (!IS_ERR(tmp)) {
-+ err = 0;
-+ if (path_init(tmp, flags, nd))
-+ err = path_walk_it(tmp, nd, it);
-+ putname(tmp);
-+ }
-+ return err;
-+}
-+
- /*
- * It's inline, so penalty for filesystems that don't use sticky bit is
- * minimal.
-@@ -1008,7 +1091,8 @@
- * for symlinks (where the permissions are checked later).
- * SMP-safe
- */
--int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
-+int open_namei_it(const char *pathname, int flag, int mode,
-+ struct nameidata *nd, struct lookup_intent *it)
- {
- int acc_mode, error = 0;
- struct inode *inode;
-@@ -1022,16 +1106,21 @@
- * The simplest case - just a plain lookup.
- */
- if (!(flag & O_CREAT)) {
-- error = path_lookup(pathname, lookup_flags(flag), nd);
-+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it);
- if (error)
- return error;
- dentry = nd->dentry;
-+ dentry->d_it = it;
- goto ok;
- }
-
- /*
- * Create - we need to know the parent.
- */
-+ if (it) {
-+ it->it_mode = mode;
-+ it->it_op |= IT_CREAT;
-+ }
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
- if (error)
- return error;
-@@ -1047,7 +1136,7 @@
-
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1056,6 +1145,8 @@
- goto exit;
- }
-
-+ dentry->d_it = it;
-+ dentry->d_it->it_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
- error = vfs_create(dir->d_inode, dentry,
-@@ -1175,8 +1266,10 @@
- return 0;
-
- exit_dput:
-+ intent_release(dentry);
- dput(dentry);
- exit:
-+ intent_release(nd->dentry);
- path_release(nd);
- return error;
-
-@@ -1196,6 +1289,8 @@
- */
- UPDATE_ATIME(dentry->d_inode);
- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(dentry);
- dput(dentry);
- if (error)
- return error;
-@@ -1217,13 +1312,20 @@
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, NULL);
- putname(nd->last.name);
- goto do_last;
- }
-
-+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd)
-+{
-+ return open_namei_it(pathname, flag, mode, nd, NULL);
-+}
-+
-+
- /* SMP-safe */
--static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
-+static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
-
-@@ -1231,7 +1333,7 @@
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1277,6 +1379,7 @@
- char * tmp;
- struct dentry * dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode };
-
- if (S_ISDIR(mode))
- return -EPERM;
-@@ -1287,11 +1390,12 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
-
- mode &= ~current->fs->umask;
- if (!IS_ERR(dentry)) {
-+ dentry->d_it = ⁢
- switch (mode & S_IFMT) {
- case 0: case S_IFREG:
- error = vfs_create(nd.dentry->d_inode,dentry,mode);
-@@ -1305,6 +1409,7 @@
- default:
- error = -EINVAL;
- }
-+ intent_release(dentry);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1345,6 +1450,7 @@
- {
- int error = 0;
- char * tmp;
-+ struct lookup_intent it = { .it_op = IT_MKDIR, .it_mode = mode };
-
- tmp = getname(pathname);
- error = PTR_ERR(tmp);
-@@ -1355,11 +1461,13 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 1);
-+ dentry = lookup_create(&nd, 1, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
-+ dentry->d_it = ⁢
- error = vfs_mkdir(nd.dentry->d_inode, dentry,
- mode & ~current->fs->umask);
-+ intent_release(dentry);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1439,6 +1547,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_RMDIR };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1460,10 +1569,12 @@
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
-+ dentry->d_it = ⁢
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-+ intent_release(dentry);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1507,6 +1618,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_UNLINK };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1519,14 +1631,16 @@
- if (nd.last_type != LAST_NORM)
- goto exit1;
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
-+ dentry->d_it = ⁢
- /* Why not before? Because we want correct error value */
- if (nd.last.name[nd.last.len])
- goto slashes;
- error = vfs_unlink(nd.dentry->d_inode, dentry);
- exit2:
-+ intent_release(dentry);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1573,6 +1687,7 @@
- int error = 0;
- char * from;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_SYMLINK };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1586,10 +1701,13 @@
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ it.it_data = from;
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
-+ dentry->d_it = ⁢
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
-+ intent_release(dentry);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1654,6 +1771,7 @@
- {
- int error;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_LINK };
-
- to = getname(newname);
- error = PTR_ERR(to);
-@@ -1670,10 +1788,12 @@
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-- new_dentry = lookup_create(&nd, 0);
-+ new_dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
-+ new_dentry->d_it = ⁢
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-+ intent_release(new_dentry);
- dput(new_dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1714,7 +1834,8 @@
- * locking].
- */
- int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- struct inode *target;
-@@ -1768,10 +1889,12 @@
- } else
- double_down(&old_dir->i_zombie,
- &new_dir->i_zombie);
-+ new_dentry->d_it = it;
- if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry);
- if (target) {
- if (!error)
- target->i_flags |= S_DEAD;
-@@ -1793,7 +1916,8 @@
- }
-
- int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -1820,10 +1944,12 @@
- DQUOT_INIT(old_dir);
- DQUOT_INIT(new_dir);
- double_down(&old_dir->i_zombie, &new_dir->i_zombie);
-+ new_dentry->d_it = it;
- if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry);
- double_up(&old_dir->i_zombie, &new_dir->i_zombie);
- if (error)
- return error;
-@@ -1835,13 +1961,14 @@
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- if (S_ISDIR(old_dentry->d_inode->i_mode))
-- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
- else
-- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
- if (!error) {
- if (old_dir == new_dir)
- inode_dir_notify(old_dir, DN_RENAME);
-@@ -1858,6 +1985,7 @@
- int error = 0;
- struct dentry * old_dir, * new_dir;
- struct dentry * old_dentry, *new_dentry;
-+ struct lookup_intent it = { .it_op = IT_RENAME };
- struct nameidata oldnd, newnd;
-
- error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
-@@ -1883,7 +2011,7 @@
-
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -1899,18 +2027,21 @@
- if (newnd.last.name[newnd.last.len])
- goto exit4;
- }
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ it.it_op = IT_RENAME2;
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, &it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-
- lock_kernel();
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, &it);
- unlock_kernel();
-
-+ intent_release(new_dentry);
- dput(new_dentry);
- exit4:
-+ intent_release(old_dentry);
- dput(old_dentry);
- exit3:
- double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
---- linux-2.4.18-lustre12-pristine/fs/open.c Wed Jun 26 00:16:14 2002
-+++ linux-2.4.18-lustre12/fs/open.c Tue Aug 13 11:19:36 2002
-@@ -19,6 +19,9 @@
- #include <asm/uaccess.h>
-
- #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
-+extern int path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it);
-+extern void intent_release(struct dentry *de);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -118,14 +120,16 @@
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
- error = -EINVAL;
- if (length < 0) /* sorry, but loff_t says... */
- goto out;
-
-- error = user_path_walk(path, &nd);
-+ error = user_path_walk_it(path, &nd, &it);
- if (error)
- goto out;
-+ nd.dentry->d_it = ⁢
- inode = nd.dentry->d_inode;
-
- /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
-@@ -168,6 +172,7 @@
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -259,10 +264,12 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
-+ nd.dentry->d_it = ⁢
- inode = nd.dentry->d_inode;
-
- error = -EROFS;
-@@ -286,6 +293,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -303,11 +311,13 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
-
- if (error)
- goto out;
-+ nd.dentry->d_it = ⁢
- inode = nd.dentry->d_inode;
-
- error = -EROFS;
-@@ -330,6 +340,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -346,6 +357,7 @@
- int old_fsuid, old_fsgid;
- kernel_cap_t old_cap;
- int res;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
- return -EINVAL;
-@@ -363,13 +375,14 @@
- else
- current->cap_effective = current->cap_permitted;
-
-- res = user_path_walk(filename, &nd);
-+ res = user_path_walk_it(filename, &nd, &it);
- if (!res) {
- res = permission(nd.dentry->d_inode, mode);
- /* SuS v2 requires we report a read only fs too */
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
- && !special_file(nd.dentry->d_inode->i_mode))
- res = -EROFS;
-+ intent_release(nd.dentry);
- path_release(&nd);
- }
-
-@@ -384,11 +397,15 @@
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
-+ error = __user_walk_it(filename,
-+ LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,
-+ &nd, &it);
- if (error)
- goto out;
-
-+ nd.dentry->d_it = ⁢
- error = permission(nd.dentry->d_inode,MAY_EXEC);
- if (error)
- goto dput_and_out;
-@@ -396,6 +411,7 @@
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -435,12 +451,14 @@
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
-- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
-+ error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
-+ LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it);
- if (error)
- goto out;
-
-+ nd.dentry->d_it = ⁢
- error = permission(nd.dentry->d_inode,MAY_EXEC);
- if (error)
- goto dput_and_out;
-@@ -453,6 +471,7 @@
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -497,12 +516,14 @@
- struct inode * inode;
- int error;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-
-+ nd.dentry->d_it = ⁢
- error = -EROFS;
- if (IS_RDONLY(inode))
- goto dput_and_out;
-@@ -518,6 +539,7 @@
- error = notify_change(nd.dentry, &newattrs);
-
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -587,10 +609,13 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
-+ nd.dentry->d_it = ⁢
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry);
- path_release(&nd);
- }
- return error;
-@@ -600,10 +625,13 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
-+ nd.dentry->d_it = ⁢
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry);
- path_release(&nd);
- }
- return error;
-@@ -637,10 +665,16 @@
- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
- * used by symlinks.
- */
-+extern int open_namei_it(const char *filename, int namei_flags, int mode,
-+ struct nameidata *nd, struct lookup_intent *it);
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
-+
- struct file *filp_open(const char * filename, int flags, int mode)
- {
- int namei_flags, error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -648,14 +681,15 @@
- if (namei_flags & O_TRUNC)
- namei_flags |= 2;
-
-- error = open_namei(filename, namei_flags, mode, &nd);
-- if (!error)
-- return dentry_open(nd.dentry, nd.mnt, flags);
-+ error = open_namei_it(filename, namei_flags, mode, &nd, &it);
-+ if (error)
-+ return ERR_PTR(error);
-
-- return ERR_PTR(error);
-+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
- }
-
--struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it)
- {
- struct file * f;
- struct inode *inode;
-@@ -698,6 +731,7 @@
- }
- f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
-
-+ intent_release(dentry);
- return f;
-
- cleanup_all:
-@@ -712,11 +746,17 @@
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(dentry);
- dput(dentry);
- mntput(mnt);
- return ERR_PTR(error);
- }
-
-+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+{
-+ return dentry_open_it(dentry, mnt, flags, NULL);
-+}
-+
- /*
- * Find an empty file descriptor entry, and mark it busy.
- */
---- linux-2.4.18-lustre12-pristine/fs/stat.c Tue May 7 19:40:30 2002
-+++ linux-2.4.18-lustre12/fs/stat.c Tue Aug 13 11:13:09 2002
-@@ -13,6 +13,7 @@
-
- #include <asm/uaccess.h>
-
-+extern void intent_release(struct dentry *de);
- /*
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
-@@ -104,10 +106,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk(name, &nd);
-+ error = user_path_walk_it(name, &nd, &it);
- if (!error) {
- error = do_getattr(nd.mnt, nd.dentry, stat);
-+ intent_release(nd.dentry);
- path_release(&nd);
- }
- return error;
-@@ -117,10 +121,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk_link(name, &nd);
-+ error = user_path_walk_link_it(name, &nd, &it);
- if (!error) {
- error = do_getattr(nd.mnt, nd.dentry, stat);
-+ intent_release(nd.dentry);
- path_release(&nd);
- }
- return error;
---- linux-2.4.18-lustre12-pristine/mm/slab.c Wed Jun 26 00:16:40 2002
-+++ linux-2.4.18-lustre12/mm/slab.c Tue Aug 13 11:13:09 2002
-@@ -1207,6 +1207,59 @@
- * Called with the cache-lock held.
- */
-
-+extern struct page *check_get_page(unsigned long kaddr);
-+struct page *page_mem_map(struct page *page);
-+static int kmem_check_cache_obj (kmem_cache_t * cachep,
-+ slab_t *slabp, void * objp)
-+{
-+ int i;
-+ unsigned int objnr;
-+
-+#if DEBUG
-+ if (cachep->flags & SLAB_RED_ZONE) {
-+ objp -= BYTES_PER_WORD;
-+ if ( *(unsigned long *)objp != RED_MAGIC2)
-+ /* Either write before start, or a double free. */
-+ return 0;
-+ if (*(unsigned long *)(objp+cachep->objsize -
-+ BYTES_PER_WORD) != RED_MAGIC2)
-+ /* Either write past end, or a double free. */
-+ return 0;
-+ }
-+#endif
-+
-+ objnr = (objp-slabp->s_mem)/cachep->objsize;
-+ if (objnr >= cachep->num)
-+ return 0;
-+ if (objp != slabp->s_mem + objnr*cachep->objsize)
-+ return 0;
-+
-+ /* Check slab's freelist to see if this obj is there. */
-+ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
-+ if (i == objnr)
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ struct page *page = check_get_page((unsigned long)objp);
-+
-+ if (!VALID_PAGE(page))
-+ return 0;
-+
-+ if (!PageSlab(page))
-+ return 0;
-+
-+ /* XXX check for freed slab objects ? */
-+ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
-+ return 0;
-+
-+ return (cachep == GET_PAGE_CACHE(page));
-+}
-+
- #if DEBUG
- static int kmem_extra_free_checks (kmem_cache_t * cachep,
- slab_t *slabp, void * objp)
---- linux-2.4.18-lustre12-pristine/scripts/mkspec Wed Jun 26 00:16:49 2002
-+++ linux-2.4.18-lustre12/scripts/mkspec Tue Aug 13 11:13:09 2002
-@@ -64,6 +64,7 @@
- fi
- # Back on track, again
- echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
-+echo 'cp vmlinux $RPM_BUILD_ROOT'"/boot/vmlinux-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
- echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
- echo ""
- echo "%clean"
+++ /dev/null
---- linux-2.4.18-lustre13-3/drivers/qsnet1/qsw/kernel_linux.c Wed Jun 26 15:40:06 2002
-+++ linux-2.4.18-lustre13-4/drivers/qsnet1/qsw/kernel_linux.c Fri Aug 23 08:42:57 2002
-@@ -225,7 +225,8 @@ kmem_to_phys(void *ptr)
- uintptr_t phys, virt = (uintptr_t)ptr;
- pte_t *pte;
-
-- if ((((unsigned long) ptr) >= VMALLOC_START && ((unsigned long) ptr) < VMALLOC_END))
-+ if (((((unsigned long) ptr) >= VMALLOC_START && ((unsigned long) ptr) < VMALLOC_END)) ||
-+ ((((unsigned long) ptr) >= PKMAP_BASE && ((unsigned long) ptr) < (PKMAP_BASE + LAST_PKMAP * PAGE_SIZE))))
- {
- pte = find_pte_k(virt);
- ASSERT(pte && !pte_none(*pte));
+++ /dev/null
-diff -ru lum-2.4.18-um30/fs/ext3/balloc.c uml-2.4.18-12.5/fs/ext3/balloc.c
---- lum-2.4.18-um30/fs/ext3/balloc.c Mon Feb 25 12:38:08 2002
-+++ uml-2.4.18-12.5/fs/ext3/balloc.c Thu Sep 19 13:40:11 2002
-@@ -276,7 +276,8 @@
- }
- lock_super (sb);
- es = sb->u.ext3_sb.s_es;
-- if (block < le32_to_cpu(es->s_first_data_block) ||
-+ if (block < le32_to_cpu(es->s_first_data_block) ||
-+ block + count < block ||
- (block + count) > le32_to_cpu(es->s_blocks_count)) {
- ext3_error (sb, "ext3_free_blocks",
- "Freeing blocks not in datazone - "
-@@ -309,17 +310,6 @@
- if (!gdp)
- goto error_return;
-
-- if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
-- in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
-- in_range (block, le32_to_cpu(gdp->bg_inode_table),
-- sb->u.ext3_sb.s_itb_per_group) ||
-- in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
-- sb->u.ext3_sb.s_itb_per_group))
-- ext3_error (sb, "ext3_free_blocks",
-- "Freeing blocks in system zones - "
-- "Block = %lu, count = %lu",
-- block, count);
--
- /*
- * We are about to start releasing blocks in the bitmap,
- * so we need undo access.
-@@ -345,14 +335,24 @@
- if (err)
- goto error_return;
-
-- for (i = 0; i < count; i++) {
-+ for (i = 0; i < count; i++, block++) {
-+ if (block == le32_to_cpu(gdp->bg_block_bitmap) ||
-+ block == le32_to_cpu(gdp->bg_inode_bitmap) ||
-+ in_range(block, le32_to_cpu(gdp->bg_inode_table),
-+ sb->u.ext2_sb.s_itb_per_group)) {
-+ ext3_error(sb, __FUNCTION__,
-+ "Freeing block in system zone - block = %lu",
-+ block);
-+ continue;
-+ }
-+
- /*
- * An HJ special. This is expensive...
- */
- #ifdef CONFIG_JBD_DEBUG
- {
- struct buffer_head *debug_bh;
-- debug_bh = sb_get_hash_table(sb, block + i);
-+ debug_bh = sb_get_hash_table(sb, block);
- if (debug_bh) {
- BUFFER_TRACE(debug_bh, "Deleted!");
- if (!bh2jh(bitmap_bh)->b_committed_data)
-@@ -365,9 +365,8 @@
- #endif
- BUFFER_TRACE(bitmap_bh, "clear bit");
- if (!ext3_clear_bit (bit + i, bitmap_bh->b_data)) {
-- ext3_error (sb, __FUNCTION__,
-- "bit already cleared for block %lu",
-- block + i);
-+ ext3_error(sb, __FUNCTION__,
-+ "bit already cleared for block %lu", block);
- BUFFER_TRACE(bitmap_bh, "bit already cleared");
- } else {
- dquot_freed_blocks++;
-@@ -415,7 +417,6 @@
- if (!err) err = ret;
-
- if (overflow && !err) {
-- block += count;
- count = overflow;
- goto do_more;
- }
-@@ -575,6 +577,7 @@
-
- ext3_debug ("goal=%lu.\n", goal);
-
-+repeat:
- /*
- * First, test whether the goal block is free.
- */
-@@ -684,10 +686,21 @@
- if (tmp == le32_to_cpu(gdp->bg_block_bitmap) ||
- tmp == le32_to_cpu(gdp->bg_inode_bitmap) ||
- in_range (tmp, le32_to_cpu(gdp->bg_inode_table),
-- sb->u.ext3_sb.s_itb_per_group))
-- ext3_error (sb, "ext3_new_block",
-- "Allocating block in system zone - "
-- "block = %u", tmp);
-+ EXT3_SB(sb)->s_itb_per_group)) {
-+ ext3_error(sb, __FUNCTION__,
-+ "Allocating block in system zone - block = %u", tmp);
-+
-+ /* Note: This will potentially use up one of the handle's
-+ * buffer credits. Normally we have way too many credits,
-+ * so that is OK. In _very_ rare cases it might not be OK.
-+ * We will trigger an assertion if we run out of credits,
-+ * and we will have to do a full fsck of the filesystem -
-+ * better than randomly corrupting filesystem metadata.
-+ */
-+ ext3_set_bit(j, bh->b_data);
-+ goto repeat;
-+ }
-+
-
- /* The superblock lock should guard against anybody else beating
- * us to this point! */
-diff -ru lum-2.4.18-um30/fs/ext3/namei.c uml-2.4.18-12.5/fs/ext3/namei.c
---- lum-2.4.18-um30/fs/ext3/namei.c Fri Nov 9 15:25:04 2001
-+++ uml-2.4.18-12.5/fs/ext3/namei.c Thu Sep 19 13:40:11 2002
-@@ -354,8 +355,8 @@
- */
- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
- dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
-- ext3_mark_inode_dirty(handle, dir);
- dir->i_version = ++event;
-+ ext3_mark_inode_dirty(handle, dir);
- BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
- ext3_journal_dirty_metadata(handle, bh);
- brelse(bh);
-@@ -464,8 +465,8 @@
- inode->i_op = &ext3_file_inode_operations;
- inode->i_fop = &ext3_file_operations;
- inode->i_mapping->a_ops = &ext3_aops;
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -489,8 +490,8 @@
- err = PTR_ERR(inode);
- if (!IS_ERR(inode)) {
- init_special_inode(inode, mode, rdev);
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -933,8 +934,8 @@
- inode->i_size = l-1;
- }
- inode->u.ext3_i.i_disksize = inode->i_size;
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- out_stop:
- ext3_journal_stop(handle, dir);
- return err;
-@@ -970,8 +971,8 @@
- ext3_inc_count(handle, inode);
- atomic_inc(&inode->i_count);
-
-- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ ext3_mark_inode_dirty(handle, inode);
- ext3_journal_stop(handle, dir);
- return err;
- }
+++ /dev/null
---- linux-2.4.18-17.8.0-uml-pristine/include/linux/lustre_version.h Wed Dec 31 19:00:00 1969
-+++ linux-2.4.18-17.8.0-uml/include/linux/lustre_version.h Tue Nov 26 07:02:14 2002
-@@ -0,0 +1 @@
-+#define LUSTRE_KERNEL_VERSION 3
---- kernel-2.4.18-pristine/arch/ia64/mm/init.c 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/arch/ia64/mm/init.c 2002-10-14 14:08:23.000000000 -0600
-@@ -37,6 +37,12 @@
-
- static unsigned long totalram_pages;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int
- do_check_pgt_cache (int low, int high)
- {
---- kernel-2.4.18-pristine/arch/i386/mm/init.c 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/arch/i386/mm/init.c 2002-10-14 14:08:23.000000000 -0600
-@@ -43,6 +43,12 @@
- static unsigned long totalram_pages;
- static unsigned long totalhigh_pages;
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+#warning FIXME: Lustre team, is this solid?
-+ return virt_to_page(kaddr);
-+}
-+
- int do_check_pgt_cache(int low, int high)
- {
- int freed = 0;
---- kernel-2.4.18-pristine/drivers/block/blkpg.c 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/drivers/block/blkpg.c 2002-10-14 14:08:23.000000000 -0600
-@@ -295,3 +295,38 @@
- }
-
- EXPORT_SYMBOL(blk_ioctl);
-+
-+#define NUM_DEV_NO_WRITE 16
-+static int dev_no_write[NUM_DEV_NO_WRITE];
-+
-+/*
-+ * Debug code for turning block devices "read-only" (will discard writes
-+ * silently). This is for filesystem crash/recovery testing.
-+ */
-+void dev_set_rdonly(kdev_t dev, int no_write)
-+{
-+ if (dev) {
-+ printk(KERN_WARNING "Turning device %s read-only\n",
-+ bdevname(dev));
-+ dev_no_write[no_write] = 0xdead0000 + dev;
-+ }
-+}
-+
-+int dev_check_rdonly(kdev_t dev) {
-+ int i;
-+
-+ for (i = 0; i < NUM_DEV_NO_WRITE; i++) {
-+ if ((dev_no_write[i] & 0xffff0000) == 0xdead0000 &&
-+ dev == (dev_no_write[i] & 0xffff))
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+void dev_clear_rdonly(int no_write) {
-+ dev_no_write[no_write] = 0;
-+}
-+
-+EXPORT_SYMBOL(dev_set_rdonly);
-+EXPORT_SYMBOL(dev_check_rdonly);
-+EXPORT_SYMBOL(dev_clear_rdonly);
---- kernel-2.4.18-pristine/drivers/block/loop.c 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/drivers/block/loop.c 2002-10-14 14:08:23.000000000 -0600
-@@ -503,6 +503,11 @@
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (dev_check_rdonly(rbh->b_rdev))
-+ goto err;
-+#endif
-+
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
---- kernel-2.4.18-pristine/drivers/ide/ide-disk.c 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/drivers/ide/ide-disk.c 2002-10-14 14:08:23.000000000 -0600
-@@ -557,6 +557,12 @@
- */
- static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
- {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (rq->cmd == WRITE && dev_check_rdonly(rq->rq_dev)) {
-+ ide_end_request(1, HWGROUP(drive));
-+ return ide_stopped;
-+ }
-+#endif
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
-
---- kernel-2.4.18-pristine/fs/ext3/Makefile 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/fs/ext3/Makefile 2002-10-14 14:08:23.000000000 -0600
-@@ -9,6 +9,8 @@
-
- O_TARGET := ext3.o
-
-+export-objs := super.o
-+
- obj-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
- ioctl.o namei.o super.o symlink.o
- obj-m := $(O_TARGET)
---- kernel-2.4.18-pristine/fs/ext3/super.c 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/fs/ext3/super.c 2002-10-14 14:08:23.000000000 -0600
-@@ -1746,7 +1746,7 @@
- unregister_filesystem(&ext3_fs_type);
- }
-
--EXPORT_NO_SYMBOLS;
-+EXPORT_SYMBOL(ext3_bread);
-
- MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
- MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
---- kernel-2.4.18-pristine/include/linux/slab.h 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/include/linux/slab.h 2002-10-14 14:08:23.000000000 -0600
-@@ -57,6 +57,7 @@
- extern int kmem_cache_shrink(kmem_cache_t *);
- extern void *kmem_cache_alloc(kmem_cache_t *, int);
- extern void kmem_cache_free(kmem_cache_t *, void *);
-+extern int kmem_cache_validate(kmem_cache_t *cachep, void *objp);
-
- extern void *kmalloc(size_t, int);
- extern void kfree(const void *);
---- kernel-2.4.18-pristine/kernel/ksyms.c 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/kernel/ksyms.c 2002-10-14 14:08:23.000000000 -0600
-@@ -306,6 +306,12 @@
- EXPORT_SYMBOL(lock_may_write);
- EXPORT_SYMBOL(dcache_readdir);
-
-+/* lustre */
-+EXPORT_SYMBOL(panic_notifier_list);
-+EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(do_kern_mount);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+
- /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
- EXPORT_SYMBOL(default_llseek);
- EXPORT_SYMBOL(dentry_open);
---- kernel-2.4.18-pristine/include/linux/dcache.h 2002-10-14 13:51:28.000000000 -0600
-+++ kernel-2.4.18/include/linux/dcache.h 2002-10-14 14:08:23.000000000 -0600
-@@ -6,6 +6,34 @@
- #include <asm/atomic.h>
- #include <linux/mount.h>
-
-+#define IT_OPEN (1)
-+#define IT_CREAT (1<<1)
-+#define IT_MKDIR (1<<2)
-+#define IT_LINK (1<<3)
-+#define IT_LINK2 (1<<4)
-+#define IT_SYMLINK (1<<5)
-+#define IT_UNLINK (1<<6)
-+#define IT_RMDIR (1<<7)
-+#define IT_RENAME (1<<8)
-+#define IT_RENAME2 (1<<9)
-+#define IT_READDIR (1<<10)
-+#define IT_GETATTR (1<<11)
-+#define IT_SETATTR (1<<12)
-+#define IT_READLINK (1<<13)
-+#define IT_MKNOD (1<<14)
-+#define IT_LOOKUP (1<<15)
-+
-+struct lookup_intent {
-+ int it_op;
-+ int it_mode;
-+ int it_disposition;
-+ int it_status;
-+ struct iattr *it_iattr;
-+ __u64 it_lock_handle[2];
-+ int it_lock_mode;
-+ void *it_data;
-+};
-+
- /*
- * linux/include/linux/dcache.h
- *
-@@ -79,6 +107,7 @@
- unsigned long d_time; /* used by d_revalidate */
- struct dentry_operations *d_op;
- struct super_block * d_sb; /* The root of the dentry tree */
-+ struct lookup_intent *d_it;
- unsigned long d_vfs_flags;
- void * d_fsdata; /* fs-specific data */
- void * d_extra_attributes; /* TUX-specific data */
-@@ -92,6 +121,8 @@
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
-+ void (*d_intent_release)(struct dentry *, struct lookup_intent *);
- };
-
- /* the dentry parameter passed to d_hash and d_compare is the parent
---- kernel-2.4.18-pristine/include/linux/fs.h 2002-10-14 13:47:27.000000000 -0600
-+++ kernel-2.4.18/include/linux/fs.h 2002-10-14 14:08:23.000000000 -0600
-@@ -572,6 +572,7 @@
-
- /* needed for tty driver, and maybe others */
- void *private_data;
-+ struct lookup_intent *f_intent;
-
- /* preallocated helper kiobuf to speedup O_DIRECT */
- struct kiobuf *f_iobuf;
-@@ -829,7 +830,9 @@
- extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
- extern int vfs_rmdir(struct inode *, struct dentry *);
- extern int vfs_unlink(struct inode *, struct dentry *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it);
-
- /*
- * File types
-@@ -890,6 +893,7 @@
- struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
-+ struct dentry * (*lookup2) (struct inode *,struct dentry *, struct lookup_intent *);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
- int (*unlink) (struct inode *,struct dentry *);
- int (*symlink) (struct inode *,struct dentry *,const char *);
-@@ -1036,6 +1040,7 @@
- extern struct vfsmount *kern_mount(struct file_system_type *);
- extern int may_umount(struct vfsmount *);
- extern long do_mount(char *, char *, char *, unsigned long, void *);
-+struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data);
- extern void umount_tree(struct vfsmount *);
-
- #define kern_umount mntput
-@@ -1370,6 +1375,7 @@
- extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
-
- extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
-+extern int FASTCALL(__user_walk_it(const char *, unsigned, struct nameidata *, struct lookup_intent *it));
- extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
- extern int FASTCALL(path_walk(const char *, struct nameidata *));
- extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
-@@ -1381,6 +1387,8 @@
- extern struct dentry * lookup_hash(struct qstr *, struct dentry *);
- #define user_path_walk(name,nd) __user_walk(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd)
- #define user_path_walk_link(name,nd) __user_walk(name, LOOKUP_POSITIVE, nd)
-+#define user_path_walk_it(name,nd,it) __user_walk_it(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, nd, it)
-+#define user_path_walk_link_it(name,nd,it) __user_walk_it(name, LOOKUP_POSITIVE, nd, it)
-
- extern void iput(struct inode *);
- extern void force_delete(struct inode *);
---- kernel-2.4.18-pristine/fs/dcache.c 2002-10-14 13:47:27.000000000 -0600
-+++ kernel-2.4.18/fs/dcache.c 2002-10-14 14:08:23.000000000 -0600
-@@ -645,6 +645,7 @@
- dentry->d_fsdata = NULL;
- dentry->d_extra_attributes = NULL;
- dentry->d_mounted = 0;
-+ dentry->d_it = NULL;
- INIT_LIST_HEAD(&dentry->d_hash);
- INIT_LIST_HEAD(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_subdirs);
---- kernel-2.4.18-pristine/fs/nfsd/vfs.c 2002-10-14 13:47:27.000000000 -0600
-+++ kernel-2.4.18/fs/nfsd/vfs.c 2002-10-14 14:08:23.000000000 -0600
-@@ -1298,7 +1298,7 @@
- err = nfserr_perm;
- } else
- #endif
-- err = vfs_rename(fdir, odentry, tdir, ndentry);
-+ err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
- unlock_kernel();
- if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
---- kernel-2.4.18-pristine/fs/namei.c 2002-10-14 13:56:44.000000000 -0600
-+++ kernel-2.4.18/fs/namei.c 2002-10-14 14:08:23.000000000 -0600
-@@ -94,6 +94,14 @@
- * XEmacs seems to be relying on it...
- */
-
-+void intent_release(struct dentry *de, struct lookup_intent *it)
-+{
-+ if (de->d_op && de->d_op->d_intent_release)
-+ de->d_op->d_intent_release(de, it);
-+
-+}
-+
-+
- /* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
-@@ -260,10 +268,19 @@
- * Internal lookup() using the new generic dcache.
- * SMP-safe
- */
--static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *cached_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * dentry = d_lookup(parent, name);
-
-+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate2) {
-+ if (!dentry->d_op->d_revalidate2(dentry, flags, it) &&
-+ !d_invalidate(dentry)) {
-+ dput(dentry);
-+ dentry = NULL;
-+ }
-+ return dentry;
-+ } else
- if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
- dput(dentry);
-@@ -281,7 +298,8 @@
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
--static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
-+static struct dentry *real_lookup(struct dentry *parent, struct qstr *name,
-+ int flags, struct lookup_intent *it)
- {
- struct dentry * result;
- struct inode *dir = parent->d_inode;
-@@ -300,6 +318,9 @@
- result = ERR_PTR(-ENOMEM);
- if (dentry) {
- lock_kernel();
-+ if (dir->i_op->lookup2)
-+ result = dir->i_op->lookup2(dir, dentry, it);
-+ else
- result = dir->i_op->lookup(dir, dentry);
- unlock_kernel();
- if (result)
-@@ -321,6 +342,12 @@
- dput(result);
- result = ERR_PTR(-ENOENT);
- }
-+ } else if (result->d_op && result->d_op->d_revalidate2) {
-+ if (!result->d_op->d_revalidate2(result, flags, it) &&
-+ !d_invalidate(result)) {
-+ dput(result);
-+ result = ERR_PTR(-ENOENT);
-+ }
- }
- return result;
- }
-@@ -447,7 +474,8 @@
- *
- * We expect 'base' to be positive and a directory.
- */
--int link_path_walk(const char * name, struct nameidata *nd)
-+int link_path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
- struct inode *inode;
-@@ -524,12 +552,12 @@
- break;
- }
- /* This does the actual lookups.. */
-- dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
- if (!dentry) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, NULL);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -563,7 +591,7 @@
- nd->dentry = dentry;
- }
- err = -ENOTDIR;
-- if (!inode->i_op->lookup)
-+ if (!inode->i_op->lookup && !inode->i_op->lookup2)
- break;
- continue;
- /* here ends the main loop */
-@@ -590,12 +618,12 @@
- if (err < 0)
- break;
- }
-- dentry = cached_lookup(nd->dentry, &this, 0);
-+ dentry = cached_lookup(nd->dentry, &this, 0, it);
- if (!dentry) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- dentry = real_lookup(nd->dentry, &this, 0);
-+ dentry = real_lookup(nd->dentry, &this, 0, it);
- err = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- break;
-@@ -619,7 +647,8 @@
- goto no_inode;
- if (lookup_flags & LOOKUP_DIRECTORY) {
- err = -ENOTDIR;
-- if (!inode->i_op || !inode->i_op->lookup)
-+ if (!inode->i_op || (!inode->i_op->lookup &&
-+ !inode->i_op->lookup2))
- break;
- }
- goto return_base;
-@@ -661,10 +690,21 @@
- return err;
- }
-
-+int link_path_walk(const char * name, struct nameidata *nd)
-+{
-+ return link_path_walk_it(name, nd, NULL);
-+}
-+
-+int path_walk_it(const char * name, struct nameidata *nd, struct lookup_intent *it)
-+{
-+ current->total_link_count = 0;
-+ return link_path_walk_it(name, nd, it);
-+}
-+
- int path_walk(const char * name, struct nameidata *nd)
- {
- current->total_link_count = 0;
-- return link_path_walk(name, nd);
-+ return link_path_walk_it(name, nd, NULL);
- }
-
- /* SMP-safe */
-@@ -749,6 +789,17 @@
- }
-
- /* SMP-safe */
-+int path_lookup_it(const char *path, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ int error = 0;
-+ if (path_init(path, flags, nd))
-+ error = path_walk_it(path, nd, it);
-+ return error;
-+}
-+
-+
-+/* SMP-safe */
- int path_lookup(const char *path, unsigned flags, struct nameidata *nd)
- {
- int error = 0;
-@@ -777,7 +828,8 @@
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
--struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+struct dentry * lookup_hash_it(struct qstr *name, struct dentry * base,
-+ struct lookup_intent *it)
- {
- struct dentry * dentry;
- struct inode *inode;
-@@ -800,13 +852,16 @@
- goto out;
- }
-
-- dentry = cached_lookup(base, name, 0);
-+ dentry = cached_lookup(base, name, 0, it);
- if (!dentry) {
- struct dentry *new = d_alloc(base, name);
- dentry = ERR_PTR(-ENOMEM);
- if (!new)
- goto out;
- lock_kernel();
-+ if (inode->i_op->lookup2)
-+ dentry = inode->i_op->lookup2(inode, new, it);
-+ else
- dentry = inode->i_op->lookup(inode, new);
- unlock_kernel();
- if (!dentry)
-@@ -818,6 +873,12 @@
- return dentry;
- }
-
-+struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
-+{
-+ return lookup_hash_it(name, base, NULL);
-+}
-+
-+
- /* SMP-safe */
- struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
- {
-@@ -839,7 +900,7 @@
- }
- this.hash = end_name_hash(hash);
-
-- return lookup_hash(&this, base);
-+ return lookup_hash_it(&this, base, NULL);
- access:
- return ERR_PTR(-EACCES);
- }
-@@ -870,6 +931,23 @@
- return err;
- }
-
-+int __user_walk_it(const char *name, unsigned flags, struct nameidata *nd,
-+ struct lookup_intent *it)
-+{
-+ char *tmp;
-+ int err;
-+
-+ tmp = getname(name);
-+ err = PTR_ERR(tmp);
-+ if (!IS_ERR(tmp)) {
-+ err = 0;
-+ if (path_init(tmp, flags, nd))
-+ err = path_walk_it(tmp, nd, it);
-+ putname(tmp);
-+ }
-+ return err;
-+}
-+
- /*
- * It's inline, so penalty for filesystems that don't use sticky bit is
- * minimal.
-@@ -1008,7 +1086,8 @@
- * for symlinks (where the permissions are checked later).
- * SMP-safe
- */
--int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
-+int open_namei_it(const char *pathname, int flag, int mode,
-+ struct nameidata *nd, struct lookup_intent *it)
- {
- int acc_mode, error = 0;
- struct inode *inode;
-@@ -1022,7 +1101,7 @@
- * The simplest case - just a plain lookup.
- */
- if (!(flag & O_CREAT)) {
-- error = path_lookup(pathname, lookup_flags(flag), nd);
-+ error = path_lookup_it(pathname, lookup_flags(flag), nd, it);
- if (error)
- return error;
- dentry = nd->dentry;
-@@ -1032,6 +1111,10 @@
- /*
- * Create - we need to know the parent.
- */
-+ if (it) {
-+ it->it_mode = mode;
-+ it->it_op |= IT_CREAT;
-+ }
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
- if (error)
- return error;
-@@ -1047,7 +1130,7 @@
-
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
-
- do_last:
- error = PTR_ERR(dentry);
-@@ -1056,6 +1139,7 @@
- goto exit;
- }
-
-+ it->it_mode = mode;
- /* Negative dentry, just create the file */
- if (!dentry->d_inode) {
- error = vfs_create(dir->d_inode, dentry,
-@@ -1175,8 +1259,10 @@
- return 0;
-
- exit_dput:
-+ intent_release(dentry, it);
- dput(dentry);
- exit:
-+ intent_release(nd->dentry, it);
- path_release(nd);
- return error;
-
-@@ -1196,6 +1282,8 @@
- */
- UPDATE_ATIME(dentry->d_inode);
- error = dentry->d_inode->i_op->follow_link(dentry, nd);
-+ if (error)
-+ intent_release(dentry, it);
- dput(dentry);
- if (error)
- return error;
-@@ -1217,13 +1305,20 @@
- }
- dir = nd->dentry;
- down(&dir->d_inode->i_sem);
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
- putname(nd->last.name);
- goto do_last;
- }
-
-+int open_namei(const char *pathname, int flag, int mode, struct nameidata *nd)
-+{
-+ return open_namei_it(pathname, flag, mode, nd, NULL);
-+}
-+
-+
- /* SMP-safe */
--static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
-+static struct dentry *lookup_create(struct nameidata *nd, int is_dir,
-+ struct lookup_intent *it)
- {
- struct dentry *dentry;
-
-@@ -1231,7 +1326,7 @@
- dentry = ERR_PTR(-EEXIST);
- if (nd->last_type != LAST_NORM)
- goto fail;
-- dentry = lookup_hash(&nd->last, nd->dentry);
-+ dentry = lookup_hash_it(&nd->last, nd->dentry, it);
- if (IS_ERR(dentry))
- goto fail;
- if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
-@@ -1277,6 +1372,7 @@
- char * tmp;
- struct dentry * dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_MKNOD, .it_mode = mode };
-
- if (S_ISDIR(mode))
- return -EPERM;
-@@ -1287,7 +1383,7 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
-
- mode &= ~current->fs->umask;
-@@ -1305,6 +1401,7 @@
- default:
- error = -EINVAL;
- }
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1345,6 +1442,7 @@
- {
- int error = 0;
- char * tmp;
-+ struct lookup_intent it = { .it_op = IT_MKDIR, .it_mode = mode };
-
- tmp = getname(pathname);
- error = PTR_ERR(tmp);
-@@ -1355,11 +1453,12 @@
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 1);
-+ dentry = lookup_create(&nd, 1, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_mkdir(nd.dentry->d_inode, dentry,
- mode & ~current->fs->umask);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1439,6 +1538,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_RMDIR };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1460,10 +1560,11 @@
- goto exit1;
- }
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_rmdir(nd.dentry->d_inode, dentry);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1507,6 +1608,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_UNLINK };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1519,7 +1621,7 @@
- if (nd.last_type != LAST_NORM)
- goto exit1;
- down(&nd.dentry->d_inode->i_sem);
-- dentry = lookup_hash(&nd.last, nd.dentry);
-+ dentry = lookup_hash_it(&nd.last, nd.dentry, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- /* Why not before? Because we want correct error value */
-@@ -1527,6 +1629,7 @@
- goto slashes;
- error = vfs_unlink(nd.dentry->d_inode, dentry);
- exit2:
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1573,6 +1676,7 @@
- int error = 0;
- char * from;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_SYMLINK };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1586,10 +1690,12 @@
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ it.it_data = from;
-+ dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(dentry);
- if (!IS_ERR(dentry)) {
- error = vfs_symlink(nd.dentry->d_inode, dentry, from);
-+ intent_release(dentry, &it);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1654,6 +1760,7 @@
- {
- int error;
- char * to;
-+ struct lookup_intent it = { .it_op = IT_LINK };
-
- to = getname(newname);
- error = PTR_ERR(to);
-@@ -1661,7 +1768,7 @@
- struct dentry *new_dentry;
- struct nameidata nd, old_nd;
-
-- error = __user_walk(oldname, LOOKUP_POSITIVE, &old_nd);
-+ error = __user_walk_it(oldname, LOOKUP_POSITIVE, &old_nd, &it);
- if (error)
- goto exit;
- error = path_lookup(to, LOOKUP_PARENT, &nd);
-@@ -1670,10 +1778,12 @@
- error = -EXDEV;
- if (old_nd.mnt != nd.mnt)
- goto out_release;
-- new_dentry = lookup_create(&nd, 0);
-+ it.it_op = IT_LINK2;
-+ new_dentry = lookup_create(&nd, 0, &it);
- error = PTR_ERR(new_dentry);
- if (!IS_ERR(new_dentry)) {
- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-+ intent_release(new_dentry, &it);
- dput(new_dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1715,7 +1822,8 @@
- * locking].
- */
- int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- struct inode *target;
-@@ -1773,6 +1881,7 @@
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- if (target) {
- if (!error)
- target->i_flags |= S_DEAD;
-@@ -1794,7 +1903,8 @@
- }
-
- int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
-
-@@ -1825,6 +1935,7 @@
- error = -EBUSY;
- else
- error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-+ intent_release(new_dentry, it);
- double_up(&old_dir->i_zombie, &new_dir->i_zombie);
- if (error)
- return error;
-@@ -1836,13 +1947,14 @@
- }
-
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-- struct inode *new_dir, struct dentry *new_dentry)
-+ struct inode *new_dir, struct dentry *new_dentry,
-+ struct lookup_intent *it)
- {
- int error;
- if (S_ISDIR(old_dentry->d_inode->i_mode))
-- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry,it);
- else
-- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-+ error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,it);
- if (!error) {
- if (old_dir == new_dir)
- inode_dir_notify(old_dir, DN_RENAME);
-@@ -1859,6 +1971,7 @@
- int error = 0;
- struct dentry * old_dir, * new_dir;
- struct dentry * old_dentry, *new_dentry;
-+ struct lookup_intent it = { .it_op = IT_RENAME };
- struct nameidata oldnd, newnd;
-
- error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
-@@ -1884,7 +1997,7 @@
-
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ old_dentry = lookup_hash_it(&oldnd.last, old_dir, &it);
- error = PTR_ERR(old_dentry);
- if (IS_ERR(old_dentry))
- goto exit3;
-@@ -1900,18 +2013,21 @@
- if (newnd.last.name[newnd.last.len])
- goto exit4;
- }
-- new_dentry = lookup_hash(&newnd.last, new_dir);
-+ it.it_op = IT_RENAME2;
-+ new_dentry = lookup_hash_it(&newnd.last, new_dir, &it);
- error = PTR_ERR(new_dentry);
- if (IS_ERR(new_dentry))
- goto exit4;
-
- lock_kernel();
- error = vfs_rename(old_dir->d_inode, old_dentry,
-- new_dir->d_inode, new_dentry);
-+ new_dir->d_inode, new_dentry, &it);
- unlock_kernel();
-
-+ intent_release(new_dentry, &it);
- dput(new_dentry);
- exit4:
-+ intent_release(old_dentry, &it); // FIXME: release same intent twice!!!
- dput(old_dentry);
- exit3:
- double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
---- kernel-2.4.18-pristine/fs/open.c 2002-10-14 13:47:27.000000000 -0600
-+++ kernel-2.4.18/fs/open.c 2002-10-14 14:08:23.000000000 -0600
-@@ -19,6 +19,9 @@
- #include <asm/uaccess.h>
-
- #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
-+extern int path_walk_it(const char *name, struct nameidata *nd,
-+ struct lookup_intent *it);
-+extern void intent_release(struct dentry *de, struct lookup_intent *it);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -118,12 +121,13 @@
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
- error = -EINVAL;
- if (length < 0) /* sorry, but loff_t says... */
- goto out;
-
-- error = user_path_walk(path, &nd);
-+ error = user_path_walk_it(path, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -168,6 +172,7 @@
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -259,8 +264,9 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -286,6 +292,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -303,8 +310,9 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
-
- if (error)
- goto out;
-@@ -330,6 +338,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -346,6 +355,7 @@
- int old_fsuid, old_fsgid;
- kernel_cap_t old_cap;
- int res;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
- if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
- return -EINVAL;
-@@ -363,13 +373,14 @@
- else
- current->cap_effective = current->cap_permitted;
-
-- res = user_path_walk(filename, &nd);
-+ res = user_path_walk_it(filename, &nd, &it);
- if (!res) {
- res = permission(nd.dentry->d_inode, mode);
- /* SuS v2 requires we report a read only fs too */
- if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
- && !special_file(nd.dentry->d_inode->i_mode))
- res = -EROFS;
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
-
-@@ -384,8 +395,11 @@
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
-+ error = __user_walk_it(filename,
-+ LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,
-+ &nd, &it);
- if (error)
- goto out;
-
-@@ -396,6 +410,7 @@
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -435,9 +450,10 @@
- {
- int error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
-- LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
-+ error = __user_walk_it(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
-+ LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd, &it);
- if (error)
- goto out;
-
-@@ -453,6 +469,7 @@
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -497,8 +514,9 @@
- struct inode * inode;
- int error;
- struct iattr newattrs;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (error)
- goto out;
- inode = nd.dentry->d_inode;
-@@ -518,6 +536,7 @@
- error = notify_change(nd.dentry, &newattrs);
-
- dput_and_out:
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- out:
- return error;
-@@ -587,10 +606,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk(filename, &nd);
-+ error = user_path_walk_it(filename, &nd, &it);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -600,10 +621,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_SETATTR };
-
-- error = user_path_walk_link(filename, &nd);
-+ error = user_path_walk_link_it(filename, &nd, &it);
- if (!error) {
- error = chown_common(nd.dentry, user, group);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -637,10 +660,16 @@
- * for the internal routines (ie open_namei()/follow_link() etc). 00 is
- * used by symlinks.
- */
-+extern int open_namei_it(const char *filename, int namei_flags, int mode,
-+ struct nameidata *nd, struct lookup_intent *it);
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it);
-+
- struct file *filp_open(const char * filename, int flags, int mode)
- {
- int namei_flags, error;
- struct nameidata nd;
-+ struct lookup_intent it = { .it_op = IT_OPEN };
-
- namei_flags = flags;
- if ((namei_flags+1) & O_ACCMODE)
-@@ -648,14 +677,15 @@
- if (namei_flags & O_TRUNC)
- namei_flags |= 2;
-
-- error = open_namei(filename, namei_flags, mode, &nd);
-- if (!error)
-- return dentry_open(nd.dentry, nd.mnt, flags);
--
-- return ERR_PTR(error);
-+ error = open_namei_it(filename, namei_flags, mode, &nd, &it);
-+ if (error)
-+ return ERR_PTR(error);
-+
-+ return dentry_open_it(nd.dentry, nd.mnt, flags, &it);
- }
-
--struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+struct file *dentry_open_it(struct dentry *dentry, struct vfsmount *mnt,
-+ int flags, struct lookup_intent *it)
- {
- struct file * f;
- struct inode *inode;
-@@ -698,6 +728,7 @@
- }
- f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
-
-+ intent_release(dentry, it);
- return f;
-
- cleanup_all:
-@@ -712,11 +743,17 @@
- cleanup_file:
- put_filp(f);
- cleanup_dentry:
-+ intent_release(dentry, it);
- dput(dentry);
- mntput(mnt);
- return ERR_PTR(error);
- }
-
-+struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
-+{
-+ return dentry_open_it(dentry, mnt, flags, NULL);
-+}
-+
- /*
- * Find an empty file descriptor entry, and mark it busy.
- */
---- kernel-2.4.18-pristine/fs/stat.c 2002-10-14 13:47:27.000000000 -0600
-+++ kernel-2.4.18/fs/stat.c 2002-10-14 14:08:23.000000000 -0600
-@@ -13,6 +13,7 @@
-
- #include <asm/uaccess.h>
-
-+extern void intent_release(struct dentry *de, struct lookup_intent *it);
- /*
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
-@@ -104,10 +105,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk(name, &nd);
-+ error = user_path_walk_it(name, &nd, &it);
- if (!error) {
- error = do_getattr(nd.mnt, nd.dentry, stat);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
-@@ -117,10 +120,12 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-
-- error = user_path_walk_link(name, &nd);
-+ error = user_path_walk_link_it(name, &nd, &it);
- if (!error) {
- error = do_getattr(nd.mnt, nd.dentry, stat);
-+ intent_release(nd.dentry, &it);
- path_release(&nd);
- }
- return error;
---- kernel-2.4.18-pristine/mm/slab.c 2002-10-14 13:47:27.000000000 -0600
-+++ kernel-2.4.18/mm/slab.c 2002-10-14 14:08:23.000000000 -0600
-@@ -1207,6 +1207,59 @@
- * Called with the cache-lock held.
- */
-
-+extern struct page *check_get_page(unsigned long kaddr);
-+struct page *page_mem_map(struct page *page);
-+static int kmem_check_cache_obj (kmem_cache_t * cachep,
-+ slab_t *slabp, void * objp)
-+{
-+ int i;
-+ unsigned int objnr;
-+
-+#if DEBUG
-+ if (cachep->flags & SLAB_RED_ZONE) {
-+ objp -= BYTES_PER_WORD;
-+ if ( *(unsigned long *)objp != RED_MAGIC2)
-+ /* Either write before start, or a double free. */
-+ return 0;
-+ if (*(unsigned long *)(objp+cachep->objsize -
-+ BYTES_PER_WORD) != RED_MAGIC2)
-+ /* Either write past end, or a double free. */
-+ return 0;
-+ }
-+#endif
-+
-+ objnr = (objp-slabp->s_mem)/cachep->objsize;
-+ if (objnr >= cachep->num)
-+ return 0;
-+ if (objp != slabp->s_mem + objnr*cachep->objsize)
-+ return 0;
-+
-+ /* Check slab's freelist to see if this obj is there. */
-+ for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
-+ if (i == objnr)
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+
-+int kmem_cache_validate(kmem_cache_t *cachep, void *objp)
-+{
-+ struct page *page = check_get_page((unsigned long)objp);
-+
-+ if (!VALID_PAGE(page))
-+ return 0;
-+
-+ if (!PageSlab(page))
-+ return 0;
-+
-+ /* XXX check for freed slab objects ? */
-+ if (!kmem_check_cache_obj(cachep, GET_PAGE_SLAB(page), objp))
-+ return 0;
-+
-+ return (cachep == GET_PAGE_CACHE(page));
-+}
-+
- #if DEBUG
- static int kmem_extra_free_checks (kmem_cache_t * cachep,
- slab_t *slabp, void * objp)
---- kernel-2.4.18-pristine/fs/jbd/commit.c 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/fs/jbd/commit.c 2002-10-14 14:08:23.000000000 -0600
-@@ -482,7 +482,7 @@
- transaction's t_log_list queue, and metadata buffers are on
- the t_iobuf_list queue.
-
-- Wait for the transactions in reverse order. That way we are
-+ Wait for the buffers in reverse order. That way we are
- less likely to be woken up until all IOs have completed, and
- so we incur less scheduling load.
- */
-@@ -575,8 +575,10 @@
-
- jbd_debug(3, "JBD: commit phase 6\n");
-
-- if (is_journal_aborted(journal))
-+ if (is_journal_aborted(journal)) {
-+ unlock_journal(journal);
- goto skip_commit;
-+ }
-
- /* Done it all: now write the commit record. We should have
- * cleaned up our previous buffers by now, so if we are in abort
-@@ -586,6 +588,7 @@
- descriptor = journal_get_descriptor_buffer(journal);
- if (!descriptor) {
- __journal_abort_hard(journal);
-+ unlock_journal(journal);
- goto skip_commit;
- }
-
-@@ -609,7 +612,6 @@
- put_bh(bh); /* One for getblk() */
- journal_unlock_journal_head(descriptor);
- }
-- lock_journal(journal);
-
- /* End of a transaction! Finally, we can do checkpoint
- processing: any buffers committed as a result of this
-@@ -618,6 +620,25 @@
-
- skip_commit:
-
-+ /* Call any callbacks that had been registered for handles in this
-+ * transaction. It is up to the callback to free any allocated
-+ * memory.
-+ */
-+ if (!list_empty(&commit_transaction->t_jcb)) {
-+ struct list_head *p, *n;
-+ int error = is_journal_aborted(journal);
-+
-+ list_for_each_safe(p, n, &commit_transaction->t_jcb) {
-+ struct journal_callback *jcb;
-+
-+ jcb = list_entry(p, struct journal_callback, jcb_list);
-+ list_del(p);
-+ jcb->jcb_func(jcb, error);
-+ }
-+ }
-+
-+ lock_journal(journal);
-+
- jbd_debug(3, "JBD: commit phase 7\n");
-
- J_ASSERT(commit_transaction->t_sync_datalist == NULL);
---- kernel-2.4.18-pristine/fs/jbd/journal.c 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/fs/jbd/journal.c 2002-10-14 14:08:23.000000000 -0600
-@@ -58,6 +58,7 @@
- #endif
- EXPORT_SYMBOL(journal_flush);
- EXPORT_SYMBOL(journal_revoke);
-+EXPORT_SYMBOL(journal_callback_set);
-
- EXPORT_SYMBOL(journal_init_dev);
- EXPORT_SYMBOL(journal_init_inode);
---- kernel-2.4.18-pristine/fs/jbd/transaction.c 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/fs/jbd/transaction.c 2002-10-14 14:08:23.000000000 -0600
-@@ -57,6 +57,7 @@
- transaction->t_state = T_RUNNING;
- transaction->t_tid = journal->j_transaction_sequence++;
- transaction->t_expires = jiffies + journal->j_commit_interval;
-+ INIT_LIST_HEAD(&transaction->t_jcb);
-
- /* Set up the commit timer for the new transaction. */
- J_ASSERT (!journal->j_commit_timer_active);
-@@ -201,6 +202,20 @@
- return 0;
- }
-
-+/* Allocate a new handle. This should probably be in a slab... */
-+static handle_t *new_handle(int nblocks)
-+{
-+ handle_t *handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+ if (!handle)
-+ return NULL;
-+ memset(handle, 0, sizeof (handle_t));
-+ handle->h_buffer_credits = nblocks;
-+ handle->h_ref = 1;
-+ INIT_LIST_HEAD(&handle->h_jcb);
-+
-+ return handle;
-+}
-+
- /*
- * Obtain a new handle.
- *
-@@ -227,14 +242,11 @@
- handle->h_ref++;
- return handle;
- }
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = new_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = start_this_handle(journal, handle);
-@@ -333,14 +345,11 @@
-
- if (is_journal_aborted(journal))
- return ERR_PTR(-EIO);
--
-- handle = jbd_kmalloc(sizeof (handle_t), GFP_NOFS);
-+
-+ handle = new_handle(nblocks);
- if (!handle)
- return ERR_PTR(-ENOMEM);
-- memset (handle, 0, sizeof (handle_t));
-
-- handle->h_buffer_credits = nblocks;
-- handle->h_ref = 1;
- current->journal_info = handle;
-
- err = try_start_this_handle(journal, handle);
-@@ -1319,6 +1328,28 @@
- #endif
-
- /*
-+ * Register a callback function for this handle. The function will be
-+ * called when the transaction that this handle is part of has been
-+ * committed to disk with the original callback data struct and the
-+ * error status of the journal as parameters. There is no guarantee of
-+ * ordering between handles within a single transaction, nor between
-+ * callbacks registered on the same handle.
-+ *
-+ * The caller is responsible for allocating the journal_callback struct.
-+ * This is to allow the caller to add as much extra data to the callback
-+ * as needed, but reduce the overhead of multiple allocations. The caller
-+ * allocated struct must start with a struct journal_callback at offset 0,
-+ * and has the caller-specific data afterwards.
-+ */
-+void journal_callback_set(handle_t *handle,
-+ void (*func)(struct journal_callback *jcb, int error),
-+ struct journal_callback *jcb)
-+{
-+ list_add(&jcb->jcb_list, &handle->h_jcb);
-+ jcb->jcb_func = func;
-+}
-+
-+/*
- * All done for a particular handle.
- *
- * There is not much action needed here. We just return any remaining
-@@ -1383,7 +1414,10 @@
- wake_up(&journal->j_wait_transaction_locked);
- }
-
-- /*
-+ /* Move callbacks from the handle to the transaction. */
-+ list_splice(&handle->h_jcb, &transaction->t_jcb);
-+
-+ /*
- * If the handle is marked SYNC, we need to set another commit
- * going! We also want to force a commit if the current
- * transaction is occupying too much of the log, or if the
---- kernel-2.4.18-pristine/include/linux/jbd.h 2002-10-14 13:47:20.000000000 -0600
-+++ kernel-2.4.18/include/linux/jbd.h 2002-10-14 14:08:23.000000000 -0600
-@@ -257,6 +257,13 @@
- return bh->b_private;
- }
-
-+#define HAVE_JOURNAL_CALLBACK_STATUS
-+struct journal_callback {
-+ struct list_head jcb_list;
-+ void (*jcb_func)(struct journal_callback *jcb, int error);
-+ /* user data goes here */
-+};
-+
- struct jbd_revoke_table_s;
-
- /* The handle_t type represents a single atomic update being performed
-@@ -287,6 +294,12 @@
- operations */
- int h_err;
-
-+ /* List of application registered callbacks for this handle.
-+ * The function(s) will be called after the transaction that
-+ * this handle is part of has been committed to disk.
-+ */
-+ struct list_head h_jcb;
-+
- /* Flags */
- unsigned int h_sync: 1; /* sync-on-close */
- unsigned int h_jdata: 1; /* force data journaling */
-@@ -406,6 +419,10 @@
-
- /* How many handles used this transaction? */
- int t_handle_count;
-+
-+ /* List of registered callback functions for this transaction.
-+ * Called when the transaction is committed. */
-+ struct list_head t_jcb;
- };
-
-
-@@ -654,6 +671,9 @@
- extern int journal_try_to_free_buffers(journal_t *, struct page *, int);
- extern int journal_stop(handle_t *);
- extern int journal_flush (journal_t *);
-+extern void journal_callback_set(handle_t *handle,
-+ void (*fn)(struct journal_callback *,int),
-+ struct journal_callback *jcb);
-
- extern void journal_lock_updates (journal_t *);
- extern void journal_unlock_updates (journal_t *);
+++ /dev/null
---- lum-pristine/arch/um/kernel/mem.c Mon Aug 12 11:05:20 2002
-+++ lum/arch/um/kernel/mem.c Thu Aug 1 18:07:35 2002
-@@ -527,6 +527,21 @@
- return(phys_mem_map(pte_val(pte)));
- }
-
-+struct page *check_get_page(unsigned long kaddr)
-+{
-+ struct page *page;
-+ struct mem_region *mr;
-+ unsigned long phys = __pa(kaddr);
-+ unsigned int n = phys_region_index(phys);
-+
-+ if (regions[n] == NULL)
-+ return NULL;
-+
-+ mr = regions[n];
-+ page = (struct page *) mr->mem_map;
-+ return page + ((phys_addr(phys)) >> PAGE_SHIFT);
-+}
-+
- struct mem_region *page_region(struct page *page, int *index_out)
- {
- int i;
-@@ -542,12 +558,14 @@
- return(region);
- }
- }
-- panic("No region found for page");
-+ //panic("No region found for page");
- return(NULL);
- }
-
- struct page *page_mem_map(struct page *page)
- {
-+ if (!page_region(page, NULL))
-+ return NULL;
- return((struct page *) page_region(page, NULL)->mem_map);
- }
-
-@@ -564,7 +582,7 @@
- (addr <= region->start + region->len))
- return(mk_phys(addr - region->start, i));
- }
-- panic("region_pa : no region for virtual address");
-+ //panic("region_pa : no region for virtual address");
- return(0);
- }
-
+++ /dev/null
---- lum/arch/um/drivers/ubd.c.orig Wed Mar 13 14:04:59 2002
-+++ lum/arch/um/drivers/ubd.c Thu Mar 28 23:39:15 2002
-@@ -693,14 +697,23 @@
- spin_unlock(&io_request_lock);
- return(1);
- }
-- if((req->cmd == WRITE) &&
-- ((dev->openflags & O_ACCMODE) == O_RDONLY)){
-- printk("Write attempted on readonly ubd device %d\n",
-- minor(req->rq_dev));
-- spin_lock(&io_request_lock);
-- end_request(0);
-- spin_unlock(&io_request_lock);
-- return(1);
-+ if (req->cmd == WRITE) {
-+#ifdef CONFIG_DEV_RDONLY
-+ if (dev_check_rdonly(req->rq_dev)) {
-+ spin_lock(&io_request_lock);
-+ end_request(1);
-+ spin_unlock(&io_request_lock);
-+ return(0);
-+ }
-+#endif
-+ if ((dev->openflags & O_ACCMODE) == O_RDONLY) {
-+ printk("Write attempted on readonly ubd device %d\n",
-+ minor(req->rq_dev));
-+ spin_lock(&io_request_lock);
-+ end_request(0);
-+ spin_unlock(&io_request_lock);
-+ return(1);
-+ }
- }
-
- block = req->sector;
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-tags
-TAGS
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-DEFS=
-
-MODULE = ptlrpc
-modulefs_DATA = ptlrpc.o
-EXTRA_PROGRAMS = ptlrpc
-
-ptlrpc_SOURCES = recovd.c recover.c connection.c rpc.c events.c service.c client.c niobuf.c pack_generic.c lproc_ptlrpc.c
-
-include $(top_srcdir)/Rules
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_ha.h>
-#include <linux/lustre_import.h>
-
-void ptlrpc_init_client(int req_portal, int rep_portal, char *name,
- struct ptlrpc_client *cl)
-{
- cl->cli_request_portal = req_portal;
- cl->cli_reply_portal = rep_portal;
- cl->cli_name = name;
-}
-
-__u8 *ptlrpc_req_to_uuid(struct ptlrpc_request *req)
-{
- return req->rq_connection->c_remote_uuid;
-}
-
-struct ptlrpc_connection *ptlrpc_uuid_to_connection(obd_uuid_t uuid)
-{
- struct ptlrpc_connection *c;
- struct lustre_peer peer;
- int err;
-
- err = kportal_uuid_to_peer(uuid, &peer);
- if (err != 0) {
- CERROR("cannot find peer %s!\n", uuid);
- return NULL;
- }
-
- c = ptlrpc_get_connection(&peer, uuid);
- if (c) {
- memcpy(c->c_remote_uuid, uuid, sizeof(c->c_remote_uuid));
- c->c_epoch++;
- }
-
- CDEBUG(D_INFO, "%s -> %p\n", uuid, c);
-
- return c;
-}
-
-void ptlrpc_readdress_connection(struct ptlrpc_connection *conn,obd_uuid_t uuid)
-{
- struct lustre_peer peer;
- int err;
-
- err = kportal_uuid_to_peer(uuid, &peer);
- if (err != 0) {
- CERROR("cannot find peer %s!\n", uuid);
- return;
- }
-
- memcpy(&conn->c_peer, &peer, sizeof(peer));
- return;
-}
-
-struct ptlrpc_bulk_desc *ptlrpc_prep_bulk(struct ptlrpc_connection *conn)
-{
- struct ptlrpc_bulk_desc *desc;
-
- OBD_ALLOC(desc, sizeof(*desc));
- if (desc != NULL) {
- desc->bd_connection = ptlrpc_connection_addref(conn);
- atomic_set(&desc->bd_refcount, 1);
- init_waitqueue_head(&desc->bd_waitq);
- INIT_LIST_HEAD(&desc->bd_page_list);
- INIT_LIST_HEAD(&desc->bd_set_chain);
- ptl_set_inv_handle(&desc->bd_md_h);
- ptl_set_inv_handle(&desc->bd_me_h);
- }
-
- return desc;
-}
-
-int ptlrpc_bulk_error(struct ptlrpc_bulk_desc *desc)
-{
- int rc = 0;
- if (desc->bd_flags & PTL_RPC_FL_TIMEOUT) {
- rc = (desc->bd_flags & PTL_RPC_FL_INTR ? -ERESTARTSYS :
- -ETIMEDOUT);
- }
- return rc;
-}
-
-struct ptlrpc_bulk_page *ptlrpc_prep_bulk_page(struct ptlrpc_bulk_desc *desc)
-{
- struct ptlrpc_bulk_page *bulk;
-
- OBD_ALLOC(bulk, sizeof(*bulk));
- if (bulk != NULL) {
- bulk->bp_desc = desc;
- list_add_tail(&bulk->bp_link, &desc->bd_page_list);
- desc->bd_page_count++;
- }
- return bulk;
-}
-
-void ptlrpc_free_bulk(struct ptlrpc_bulk_desc *desc)
-{
- struct list_head *tmp, *next;
- ENTRY;
- if (desc == NULL) {
- EXIT;
- return;
- }
-
- LASSERT(list_empty(&desc->bd_set_chain));
-
- list_for_each_safe(tmp, next, &desc->bd_page_list) {
- struct ptlrpc_bulk_page *bulk;
- bulk = list_entry(tmp, struct ptlrpc_bulk_page, bp_link);
- ptlrpc_free_bulk_page(bulk);
- }
-
- ptlrpc_put_connection(desc->bd_connection);
-
- OBD_FREE(desc, sizeof(*desc));
- EXIT;
-}
-
-void ptlrpc_free_bulk_page(struct ptlrpc_bulk_page *bulk)
-{
- ENTRY;
- if (bulk == NULL) {
- EXIT;
- return;
- }
-
- list_del(&bulk->bp_link);
- bulk->bp_desc->bd_page_count--;
- OBD_FREE(bulk, sizeof(*bulk));
- EXIT;
-}
-
-static int ll_sync_brw_timeout(void *data)
-{
- struct obd_brw_set *set = data;
- struct list_head *tmp;
- int failed = 0;
- ENTRY;
-
- LASSERT(set);
-
- set->brw_flags |= PTL_RPC_FL_TIMEOUT;
-
- list_for_each(tmp, &set->brw_desc_head) {
- struct ptlrpc_bulk_desc *desc =
- list_entry(tmp, struct ptlrpc_bulk_desc, bd_set_chain);
-
- /* Skip descriptors that were completed successfully. */
- if (desc->bd_flags & (PTL_BULK_FL_RCVD | PTL_BULK_FL_SENT))
- continue;
-
- LASSERT(desc->bd_connection);
-
- /* If PtlMDUnlink succeeds, then it hasn't completed yet. If it
- * fails, the bulk finished _just_ in time (after the timeout
- * fired but before we got this far) and we'll let it live.
- */
- if (PtlMDUnlink(desc->bd_md_h) != 0) {
- CERROR("Near-miss on OST %s -- need to adjust "
- "obd_timeout?\n",
- desc->bd_connection->c_remote_uuid);
- continue;
- }
-
- CERROR("IO of %d pages to/from %s:%d (conn %p) timed out\n",
- desc->bd_page_count, desc->bd_connection->c_remote_uuid,
- desc->bd_portal, desc->bd_connection);
-
- /* This one will "never" arrive, don't wait for it. */
- if (atomic_dec_and_test(&set->brw_refcount))
- wake_up(&set->brw_waitq);
-
- if (class_signal_connection_failure)
- class_signal_connection_failure(desc->bd_connection);
- else
- failed = 1;
- }
-
- /* 0 = We go back to sleep, until we're resumed or interrupted */
- /* 1 = We can't be recovered, just abort the syscall with -ETIMEDOUT */
- RETURN(failed);
-}
-
-static int ll_sync_brw_intr(void *data)
-{
- struct obd_brw_set *set = data;
-
- ENTRY;
- set->brw_flags |= PTL_RPC_FL_INTR;
- RETURN(1); /* ignored, as of this writing */
-}
-
-int ll_brw_sync_wait(struct obd_brw_set *set, int phase)
-{
- struct l_wait_info lwi;
- struct list_head *tmp, *next;
- int rc = 0;
- ENTRY;
-
- switch(phase) {
- case CB_PHASE_START:
- lwi = LWI_TIMEOUT_INTR(obd_timeout * HZ, ll_sync_brw_timeout,
- ll_sync_brw_intr, set);
- rc = l_wait_event(set->brw_waitq,
- atomic_read(&set->brw_refcount) == 0, &lwi);
-
- list_for_each_safe(tmp, next, &set->brw_desc_head) {
- struct ptlrpc_bulk_desc *desc =
- list_entry(tmp, struct ptlrpc_bulk_desc,
- bd_set_chain);
- list_del_init(&desc->bd_set_chain);
- ptlrpc_bulk_decref(desc);
- }
- break;
- case CB_PHASE_FINISH:
- if (atomic_dec_and_test(&set->brw_refcount))
- wake_up(&set->brw_waitq);
- break;
- default:
- LBUG();
- }
-
- RETURN(rc);
-}
-
-struct ptlrpc_request *ptlrpc_prep_req(struct obd_import *imp, int opcode,
- int count, int *lengths, char **bufs)
-{
- struct ptlrpc_connection *conn = imp->imp_connection;
- struct ptlrpc_request *request;
- int rc;
- ENTRY;
-
- OBD_ALLOC(request, sizeof(*request));
- if (!request) {
- CERROR("request allocation out of memory\n");
- RETURN(NULL);
- }
-
- rc = lustre_pack_msg(count, lengths, bufs,
- &request->rq_reqlen, &request->rq_reqmsg);
- if (rc) {
- CERROR("cannot pack request %d\n", rc);
- OBD_FREE(request, sizeof(*request));
- RETURN(NULL);
- }
-
- request->rq_level = LUSTRE_CONN_FULL;
- request->rq_type = PTL_RPC_MSG_REQUEST;
- request->rq_import = imp;
-
- /* XXX FIXME bug 625069 */
- request->rq_request_portal = imp->imp_client->cli_request_portal;
- request->rq_reply_portal = imp->imp_client->cli_reply_portal;
-
- request->rq_connection = ptlrpc_connection_addref(conn);
-
- INIT_LIST_HEAD(&request->rq_list);
- atomic_set(&request->rq_refcount, 1);
-
- spin_lock(&imp->imp_lock);
- request->rq_xid = HTON__u32(++imp->imp_last_xid);
- spin_unlock(&imp->imp_lock);
-
- request->rq_reqmsg->magic = PTLRPC_MSG_MAGIC;
- request->rq_reqmsg->version = PTLRPC_MSG_VERSION;
- request->rq_reqmsg->opc = HTON__u32(opcode);
- request->rq_reqmsg->flags = 0;
-
- ptlrpc_hdl2req(request, &imp->imp_handle);
- RETURN(request);
-}
-
-static void __ptlrpc_free_req(struct ptlrpc_request *request, int locked)
-{
- ENTRY;
- if (request == NULL) {
- EXIT;
- return;
- }
-
- if (atomic_read(&request->rq_refcount) != 0) {
- CERROR("freeing request %p (%d->%s:%d) with refcount %d\n",
- request, request->rq_reqmsg->opc,
- request->rq_connection->c_remote_uuid,
- request->rq_import->imp_client->cli_request_portal,
- request->rq_refcount);
- /* LBUG(); */
- }
-
- if (request->rq_repmsg != NULL) {
- OBD_FREE(request->rq_repmsg, request->rq_replen);
- request->rq_repmsg = NULL;
- request->rq_reply_md.start = NULL;
- }
- if (request->rq_reqmsg != NULL) {
- OBD_FREE(request->rq_reqmsg, request->rq_reqlen);
- request->rq_reqmsg = NULL;
- }
-
- if (request->rq_import) {
- if (!locked)
- spin_lock(&request->rq_import->imp_lock);
- list_del_init(&request->rq_list);
- if (!locked)
- spin_unlock(&request->rq_import->imp_lock);
- }
-
- ptlrpc_put_connection(request->rq_connection);
- OBD_FREE(request, sizeof(*request));
- EXIT;
-}
-
-void ptlrpc_free_req(struct ptlrpc_request *request)
-{
- __ptlrpc_free_req(request, 0);
-}
-
-static int __ptlrpc_req_finished(struct ptlrpc_request *request, int locked)
-{
- ENTRY;
- if (request == NULL)
- RETURN(1);
-
- if (atomic_dec_and_test(&request->rq_refcount)) {
- __ptlrpc_free_req(request, locked);
- RETURN(1);
- }
-
- DEBUG_REQ(D_INFO, request, "refcount now %u",
- atomic_read(&request->rq_refcount));
- RETURN(0);
-}
-
-void ptlrpc_req_finished(struct ptlrpc_request *request)
-{
- __ptlrpc_req_finished(request, 0);
-}
-
-static int ptlrpc_check_reply(struct ptlrpc_request *req)
-{
- int rc = 0;
-
- ENTRY;
- if (req->rq_repmsg != NULL) {
- req->rq_transno = NTOH__u64(req->rq_repmsg->transno);
- req->rq_flags |= PTL_RPC_FL_REPLIED;
- GOTO(out, rc = 1);
- }
-
- if (req->rq_flags & PTL_RPC_FL_RESEND) {
- ENTRY;
- DEBUG_REQ(D_ERROR, req, "RESEND:");
- GOTO(out, rc = 1);
- }
-
- if (req->rq_flags & PTL_RPC_FL_ERR) {
- ENTRY;
- DEBUG_REQ(D_ERROR, req, "ABORTED:");
- GOTO(out, rc = 1);
- }
-
- if (req->rq_flags & PTL_RPC_FL_RESTART) {
- DEBUG_REQ(D_ERROR, req, "RESTART:");
- GOTO(out, rc = 1);
- }
- EXIT;
- out:
- DEBUG_REQ(D_NET, req, "rc = %d for", rc);
- return rc;
-}
-
-static int ptlrpc_check_status(struct ptlrpc_request *req)
-{
- int err;
- ENTRY;
-
- err = req->rq_repmsg->status;
- if (req->rq_repmsg->type == NTOH__u32(PTL_RPC_MSG_ERR)) {
- DEBUG_REQ(D_ERROR, req, "type == PTL_RPC_MSG_ERR");
- RETURN(err ? err : -EINVAL);
- }
-
- if (err < 0) {
- DEBUG_REQ(D_ERROR, req, "status is %d", err);
- } else if (err > 0) {
- /* XXX: translate this error from net to host */
- DEBUG_REQ(D_INFO, req, "status is %d", err);
- }
-
- RETURN(err);
-}
-
-static void ptlrpc_cleanup_request_buf(struct ptlrpc_request *request)
-{
- OBD_FREE(request->rq_reqmsg, request->rq_reqlen);
- request->rq_reqmsg = NULL;
- request->rq_reqlen = 0;
-}
-
-/* Abort this request and cleanup any resources associated with it. */
-static int ptlrpc_abort(struct ptlrpc_request *request)
-{
- /* First remove the ME for the reply; in theory, this means
- * that we can tear down the buffer safely. */
- PtlMEUnlink(request->rq_reply_me_h);
- OBD_FREE(request->rq_reply_md.start, request->rq_replen);
- request->rq_repmsg = NULL;
- request->rq_replen = 0;
- return 0;
-}
-
-/* caller must hold imp->imp_lock */
-void ptlrpc_free_committed(struct obd_import *imp)
-{
- struct list_head *tmp, *saved;
- struct ptlrpc_request *req;
- ENTRY;
-
-#ifndef __arch_um__
- LASSERT(spin_is_locked(&imp->imp_lock));
-#endif
-
- CDEBUG(D_HA, "committing for xid "LPU64", last_committed "LPU64"\n",
- imp->imp_peer_last_xid, imp->imp_peer_committed_transno);
-
- list_for_each_safe(tmp, saved, &imp->imp_replay_list) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
-
- if (req->rq_flags & PTL_RPC_FL_REPLAY) {
- DEBUG_REQ(D_HA, req, "keeping (FL_REPLAY)");
- continue;
- }
-
- /* not yet committed */
- if (req->rq_transno > imp->imp_peer_committed_transno) {
- DEBUG_REQ(D_HA, req, "stopping search");
- break;
- }
-
- DEBUG_REQ(D_HA, req, "committing (last_committed "LPU64")",
- imp->imp_peer_committed_transno);
- __ptlrpc_req_finished(req, 1);
- }
-
- EXIT;
- return;
-}
-
-void ptlrpc_cleanup_client(struct obd_import *imp)
-{
- struct list_head *tmp, *saved;
- struct ptlrpc_request *req;
- struct ptlrpc_connection *conn = imp->imp_connection;
- ENTRY;
-
- LASSERT(conn);
-
- spin_lock(&imp->imp_lock);
- list_for_each_safe(tmp, saved, &imp->imp_replay_list) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
-
- /* XXX we should make sure that nobody's sleeping on these! */
- DEBUG_REQ(D_HA, req, "cleaning up from sending list");
- list_del_init(&req->rq_list);
- req->rq_import = NULL;
- __ptlrpc_req_finished(req, 0);
- }
- spin_unlock(&imp->imp_lock);
-
- EXIT;
- return;
-}
-
-void ptlrpc_continue_req(struct ptlrpc_request *req)
-{
- ENTRY;
- DEBUG_REQ(D_HA, req, "continuing delayed request");
- req->rq_reqmsg->addr = req->rq_import->imp_handle.addr;
- req->rq_reqmsg->cookie = req->rq_import->imp_handle.cookie;
- wake_up(&req->rq_wait_for_rep);
- EXIT;
-}
-
-void ptlrpc_resend_req(struct ptlrpc_request *req)
-{
- ENTRY;
- DEBUG_REQ(D_HA, req, "resending");
- req->rq_reqmsg->addr = req->rq_import->imp_handle.addr;
- req->rq_reqmsg->cookie = req->rq_import->imp_handle.cookie;
- req->rq_status = -EAGAIN;
- req->rq_level = LUSTRE_CONN_RECOVD;
- req->rq_flags |= PTL_RPC_FL_RESEND;
- req->rq_flags &= ~PTL_RPC_FL_TIMEOUT;
- wake_up(&req->rq_wait_for_rep);
- EXIT;
-}
-
-void ptlrpc_restart_req(struct ptlrpc_request *req)
-{
- ENTRY;
- DEBUG_REQ(D_HA, req, "restarting (possibly-)completed request");
- req->rq_status = -ERESTARTSYS;
- req->rq_flags |= PTL_RPC_FL_RESTART;
- req->rq_flags &= ~PTL_RPC_FL_TIMEOUT;
- wake_up(&req->rq_wait_for_rep);
- EXIT;
-}
-
-static int expired_request(void *data)
-{
- struct ptlrpc_request *req = data;
-
- ENTRY;
- if (!req) {
- CERROR("NULL req!");
- LBUG();
- RETURN(0);
- }
-
- DEBUG_REQ(D_ERROR, req, "timeout");
- req->rq_flags |= PTL_RPC_FL_TIMEOUT;
-
- if (!req->rq_import) {
- DEBUG_REQ(D_ERROR, req, "NULL import");
- LBUG();
- RETURN(0);
- }
-
- if (!req->rq_import->imp_connection) {
- DEBUG_REQ(D_ERROR, req, "NULL connection");
- LBUG();
- RETURN(0);
- }
-
- if (!req->rq_import->imp_connection->c_recovd_data.rd_recovd)
- RETURN(1);
-
- req->rq_timeout = 0;
- recovd_conn_fail(req->rq_import->imp_connection);
-
-#if 0
- /* If this request is for recovery or other primordial tasks,
- * don't go back to sleep.
- */
- if (req->rq_level < LUSTRE_CONN_FULL)
- RETURN(1);
-#endif
- RETURN(0);
-}
-
-static int interrupted_request(void *data)
-{
- struct ptlrpc_request *req = data;
- ENTRY;
- req->rq_flags |= PTL_RPC_FL_INTR;
- RETURN(1); /* ignored, as of this writing */
-}
-
-/* If the import has been invalidated (such as by an OST failure), the
- * request must fail with -EIO.
- *
- * Must be called with imp_lock held, will drop it if it returns -EIO.
- */
-#define EIO_IF_INVALID(req) \
-if (req->rq_import->imp_flags & IMP_INVALID) { \
- DEBUG_REQ(D_ERROR, req, "IMP_INVALID:"); \
- spin_unlock(&imp->imp_lock); \
- RETURN(-EIO); \
-}
-
-int ptlrpc_queue_wait(struct ptlrpc_request *req)
-{
- int rc = 0;
- struct l_wait_info lwi;
- struct obd_import *imp = req->rq_import;
- struct ptlrpc_connection *conn = imp->imp_connection;
- ENTRY;
-
- init_waitqueue_head(&req->rq_wait_for_rep);
-
- /* for distributed debugging */
- req->rq_reqmsg->status = HTON__u32(current->pid);
- CDEBUG(D_RPCTRACE, "Sending RPC pid:xid:nid:opc %d:"LPU64":%x:%d\n",
- NTOH__u32(req->rq_reqmsg->status), req->rq_xid,
- conn->c_peer.peer_nid, NTOH__u32(req->rq_reqmsg->opc));
-
- if (req->rq_level > imp->imp_level) {
- spin_lock(&imp->imp_lock);
- EIO_IF_INVALID(req);
- list_del(&req->rq_list);
- list_add_tail(&req->rq_list, &imp->imp_delayed_list);
- spin_unlock(&imp->imp_lock);
-
- DEBUG_REQ(D_HA, req, "\"%s\" waiting for recovery: (%d < %d)",
- current->comm, req->rq_level, imp->imp_level);
- lwi = LWI_INTR(NULL, NULL);
- rc = l_wait_event(req->rq_wait_for_rep,
- (req->rq_level <= imp->imp_level) ||
- (req->rq_flags & PTL_RPC_FL_ERR), &lwi);
-
- spin_lock(&imp->imp_lock);
- list_del_init(&req->rq_list);
- spin_unlock(&imp->imp_lock);
-
- if (req->rq_flags & PTL_RPC_FL_ERR)
- RETURN(-EIO);
-
- if (rc)
- RETURN(rc);
-
- CERROR("process %d resumed\n", current->pid);
- }
- resend:
- req->rq_timeout = obd_timeout;
- spin_lock(&imp->imp_lock);
- EIO_IF_INVALID(req);
-
- LASSERT(list_empty(&req->rq_list));
- list_add_tail(&req->rq_list, &imp->imp_sending_list);
- spin_unlock(&imp->imp_lock);
- rc = ptl_send_rpc(req);
- if (rc) {
- CDEBUG(D_HA, "error %d, opcode %d, need recovery\n", rc,
- req->rq_reqmsg->opc);
- /* sleep for a jiffy, then trigger recovery */
- lwi = LWI_TIMEOUT_INTR(1, expired_request,
- interrupted_request, req);
- } else {
- DEBUG_REQ(D_NET, req, "-- sleeping");
- lwi = LWI_TIMEOUT_INTR(req->rq_timeout * HZ, expired_request,
- interrupted_request, req);
- }
- l_wait_event(req->rq_wait_for_rep, ptlrpc_check_reply(req), &lwi);
- DEBUG_REQ(D_NET, req, "-- done sleeping");
-
- spin_lock(&imp->imp_lock);
- list_del_init(&req->rq_list);
- spin_unlock(&imp->imp_lock);
-
- if (req->rq_flags & PTL_RPC_FL_ERR) {
- ptlrpc_abort(req);
- GOTO(out, rc = -EIO);
- }
-
- /* Don't resend if we were interrupted. */
- if ((req->rq_flags & (PTL_RPC_FL_RESEND | PTL_RPC_FL_INTR)) ==
- PTL_RPC_FL_RESEND) {
- req->rq_flags &= ~PTL_RPC_FL_RESEND;
- DEBUG_REQ(D_HA, req, "resending: ");
- goto resend;
- }
-
- if (req->rq_flags & PTL_RPC_FL_INTR) {
- if (!(req->rq_flags & PTL_RPC_FL_TIMEOUT))
- LBUG(); /* should only be interrupted if we timed out */
- /* Clean up the dangling reply buffers */
- ptlrpc_abort(req);
- GOTO(out, rc = -EINTR);
- }
-
- if (req->rq_flags & PTL_RPC_FL_TIMEOUT)
- GOTO(out, rc = -ETIMEDOUT);
-
- if (!(req->rq_flags & PTL_RPC_FL_REPLIED))
- GOTO(out, rc = req->rq_status);
-
- rc = lustre_unpack_msg(req->rq_repmsg, req->rq_replen);
- if (rc) {
- CERROR("unpack_rep failed: %d\n", rc);
- GOTO(out, rc);
- }
-#if 0
- /* FIXME: Enable when BlueArc makes new release */
- if (req->rq_repmsg->type != PTL_RPC_MSG_REPLY &&
- req->rq_repmsg->type != PTL_RPC_MSG_ERR) {
- CERROR("invalid packet type received (type=%u)\n",
- req->rq_repmsg->type);
- LBUG();
- GOTO(out, rc = -EINVAL);
- }
-#endif
- CDEBUG(D_NET, "got rep "LPU64"\n", req->rq_xid);
- if (req->rq_repmsg->status == 0)
- CDEBUG(D_NET, "--> buf %p len %d status %d\n", req->rq_repmsg,
- req->rq_replen, req->rq_repmsg->status);
-
-
- if (req->rq_import->imp_flags & IMP_REPLAYABLE) {
- spin_lock(&imp->imp_lock);
- if (req->rq_flags & PTL_RPC_FL_REPLAY || req->rq_transno != 0) {
- /* Balanced in ptlrpc_free_committed, usually. */
- atomic_inc(&req->rq_refcount);
- list_add_tail(&req->rq_list, &imp->imp_replay_list);
- }
-
- if (req->rq_transno > imp->imp_max_transno) {
- imp->imp_max_transno = req->rq_transno;
- } else if (req->rq_transno != 0 &&
- imp->imp_level == LUSTRE_CONN_FULL) {
- CERROR("got transno "LPD64" after "LPD64": recovery "
- "may not work\n", req->rq_transno,
- imp->imp_max_transno);
- }
-
- /* Replay-enabled imports return commit-status information. */
- imp->imp_peer_last_xid = req->rq_repmsg->last_xid;
- imp->imp_peer_committed_transno =
- req->rq_repmsg->last_committed;
- ptlrpc_free_committed(imp);
- spin_unlock(&imp->imp_lock);
- }
-
- rc = ptlrpc_check_status(req);
-
- EXIT;
- out:
- return rc;
-}
-
-#undef EIO_IF_INVALID
-
-int ptlrpc_replay_req(struct ptlrpc_request *req)
-{
- int rc = 0, old_level, old_status = 0;
- // struct ptlrpc_client *cli = req->rq_import->imp_client;
- struct l_wait_info lwi;
- ENTRY;
-
- init_waitqueue_head(&req->rq_wait_for_rep);
- DEBUG_REQ(D_NET, req, "");
-
- req->rq_timeout = obd_timeout;
- req->rq_reqmsg->addr = req->rq_import->imp_handle.addr;
- req->rq_reqmsg->cookie = req->rq_import->imp_handle.cookie;
-
- /* temporarily set request to RECOVD level (reset at out:) */
- old_level = req->rq_level;
- if (req->rq_flags & PTL_RPC_FL_REPLIED)
- old_status = req->rq_repmsg->status;
- req->rq_level = LUSTRE_CONN_RECOVD;
- rc = ptl_send_rpc(req);
- if (rc) {
- CERROR("error %d, opcode %d\n", rc, req->rq_reqmsg->opc);
- ptlrpc_cleanup_request_buf(req);
- // up(&cli->cli_rpc_sem);
- GOTO(out, rc = -rc);
- }
-
- CDEBUG(D_OTHER, "-- sleeping\n");
- lwi = LWI_INTR(NULL, NULL); /* XXX needs timeout, nested recovery */
- l_wait_event(req->rq_wait_for_rep, ptlrpc_check_reply(req), &lwi);
- CDEBUG(D_OTHER, "-- done\n");
-
- // up(&cli->cli_rpc_sem);
-
- if (!(req->rq_flags & PTL_RPC_FL_REPLIED)) {
- CERROR("Unknown reason for wakeup\n");
- /* XXX Phil - I end up here when I kill obdctl */
- ptlrpc_abort(req);
- GOTO(out, rc = -EINTR);
- }
-
- rc = lustre_unpack_msg(req->rq_repmsg, req->rq_replen);
- if (rc) {
- CERROR("unpack_rep failed: %d\n", rc);
- GOTO(out, rc);
- }
-
- CDEBUG(D_NET, "got rep "LPD64"\n", req->rq_xid);
-
- /* let the callback do fixups, possibly including in the request */
- if (req->rq_replay_cb)
- req->rq_replay_cb(req);
-
- if ((req->rq_flags & PTL_RPC_FL_REPLIED) &&
- req->rq_repmsg->status != old_status) {
- DEBUG_REQ(D_HA, req, "status %d, old was %d",
- req->rq_repmsg->status, old_status);
- }
-
- out:
- req->rq_level = old_level;
- RETURN(rc);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_net.h>
-
-static spinlock_t conn_lock;
-static struct list_head conn_list;
-static struct list_head conn_unused_list;
-
-/* If UUID is NULL, c->c_remote_uuid must be all zeroes
- * If UUID is non-NULL, c->c_remote_uuid must match. */
-static int match_connection_uuid(struct ptlrpc_connection *c, obd_uuid_t uuid)
-{
- obd_uuid_t zero_uuid = {0};
-
- if (uuid)
- return memcmp(c->c_remote_uuid, uuid, sizeof(uuid));
-
- return memcmp(c->c_remote_uuid, zero_uuid, sizeof(zero_uuid));
-}
-
-struct ptlrpc_connection *ptlrpc_get_connection(struct lustre_peer *peer,
- obd_uuid_t uuid)
-{
- struct list_head *tmp, *pos;
- struct ptlrpc_connection *c;
- ENTRY;
-
- CDEBUG(D_INFO, "peer is %08x %08lx %08lx\n",
- peer->peer_nid, peer->peer_ni.nal_idx, peer->peer_ni.handle_idx);
-
- spin_lock(&conn_lock);
- list_for_each(tmp, &conn_list) {
- c = list_entry(tmp, struct ptlrpc_connection, c_link);
- if (memcmp(peer, &c->c_peer, sizeof(*peer)) == 0 &&
- !match_connection_uuid(c, uuid)) {
- ptlrpc_connection_addref(c);
- GOTO(out, c);
- }
- }
-
- list_for_each_safe(tmp, pos, &conn_unused_list) {
- c = list_entry(tmp, struct ptlrpc_connection, c_link);
- if (memcmp(peer, &c->c_peer, sizeof(*peer)) == 0 &&
- !match_connection_uuid(c, uuid)) {
- ptlrpc_connection_addref(c);
- list_del(&c->c_link);
- list_add(&c->c_link, &conn_list);
- GOTO(out, c);
- }
- }
-
- /* FIXME: this should be a slab once we can validate slab addresses
- * without OOPSing */
- OBD_ALLOC(c, sizeof(*c));
- if (c == NULL)
- GOTO(out, c);
-
- c->c_generation = 1;
- c->c_epoch = 1;
- c->c_bootcount = 0;
- c->c_flags = 0;
- if (uuid)
- strcpy(c->c_remote_uuid, uuid);
- INIT_LIST_HEAD(&c->c_imports);
- INIT_LIST_HEAD(&c->c_exports);
- INIT_LIST_HEAD(&c->c_sb_chain);
- INIT_LIST_HEAD(&c->c_recovd_data.rd_managed_chain);
- INIT_LIST_HEAD(&c->c_delayed_head);
- atomic_set(&c->c_refcount, 0);
- ptlrpc_connection_addref(c);
- spin_lock_init(&c->c_lock);
-
- memcpy(&c->c_peer, peer, sizeof(c->c_peer));
- list_add(&c->c_link, &conn_list);
-
- EXIT;
- out:
- spin_unlock(&conn_lock);
- return c;
-}
-
-int ptlrpc_put_connection(struct ptlrpc_connection *c)
-{
- int rc = 0;
- ENTRY;
-
- if (c == NULL) {
- CERROR("NULL connection\n");
- RETURN(0);
- }
-
- CDEBUG(D_INFO, "connection=%p refcount %d\n",
- c, atomic_read(&c->c_refcount) - 1);
- if (atomic_dec_and_test(&c->c_refcount)) {
- recovd_conn_unmanage(c);
- spin_lock(&conn_lock);
- list_del(&c->c_link);
- list_add(&c->c_link, &conn_unused_list);
- spin_unlock(&conn_lock);
- rc = 1;
- }
- if (atomic_read(&c->c_refcount) < 0)
- CERROR("connection %p refcount %d!\n",
- c, atomic_read(&c->c_refcount));
-
- RETURN(rc);
-}
-
-struct ptlrpc_connection *ptlrpc_connection_addref(struct ptlrpc_connection *c)
-{
- ENTRY;
- CDEBUG(D_INFO, "connection=%p refcount %d\n",
- c, atomic_read(&c->c_refcount) + 1);
- atomic_inc(&c->c_refcount);
- RETURN(c);
-}
-
-void ptlrpc_init_connection(void)
-{
- INIT_LIST_HEAD(&conn_list);
- INIT_LIST_HEAD(&conn_unused_list);
- conn_lock = SPIN_LOCK_UNLOCKED;
-}
-
-void ptlrpc_cleanup_connection(void)
-{
- struct list_head *tmp, *pos;
- struct ptlrpc_connection *c;
-
- spin_lock(&conn_lock);
- list_for_each_safe(tmp, pos, &conn_unused_list) {
- c = list_entry(tmp, struct ptlrpc_connection, c_link);
- list_del(&c->c_link);
- OBD_FREE(c, sizeof(*c));
- }
- list_for_each_safe(tmp, pos, &conn_list) {
- c = list_entry(tmp, struct ptlrpc_connection, c_link);
- CERROR("Connection %p/%s has refcount %d (nid=%lu)\n",
- c, c->c_remote_uuid, atomic_read(&c->c_refcount),
- (unsigned long)c->c_peer.peer_nid);
- list_del(&c->c_link);
- OBD_FREE(c, sizeof(*c));
- }
- spin_unlock(&conn_lock);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/module.h>
-#include <linux/obd_support.h>
-#include <linux/lustre_net.h>
-
-ptl_handle_eq_t request_out_eq, reply_in_eq, reply_out_eq, bulk_source_eq,
- bulk_sink_eq;
-static const ptl_handle_ni_t *socknal_nip = NULL, *toenal_nip = NULL,
- *qswnal_nip = NULL, *gmnal_nip = NULL;
-
-/*
- * Free the packet when it has gone out
- */
-static int request_out_callback(ptl_event_t *ev)
-{
- struct ptlrpc_request *req = ev->mem_desc.user_ptr;
- ENTRY;
-
- /* requests always contiguous */
- LASSERT((ev->mem_desc.options & PTL_MD_IOV) == 0);
-
- if (ev->type != PTL_EVENT_SENT) {
- // XXX make sure we understand all events, including ACK's
- CERROR("Unknown event %d\n", ev->type);
- LBUG();
- }
-
- /* this balances the atomic_inc in ptl_send_rpc */
- ptlrpc_req_finished(req);
- RETURN(1);
-}
-
-
-/*
- * Free the packet when it has gone out
- */
-static int reply_out_callback(ptl_event_t *ev)
-{
- ENTRY;
-
- /* replies always contiguous */
- LASSERT((ev->mem_desc.options & PTL_MD_IOV) == 0);
-
- if (ev->type == PTL_EVENT_SENT) {
- OBD_FREE(ev->mem_desc.start, ev->mem_desc.length);
- } else {
- // XXX make sure we understand all events, including ACK's
- CERROR("Unknown event %d\n", ev->type);
- LBUG();
- }
-
- RETURN(1);
-}
-
-/*
- * Wake up the thread waiting for the reply once it comes in.
- */
-static int reply_in_callback(ptl_event_t *ev)
-{
- struct ptlrpc_request *req = ev->mem_desc.user_ptr;
- ENTRY;
-
- /* replies always contiguous */
- LASSERT((ev->mem_desc.options & PTL_MD_IOV) == 0);
-
- if (req->rq_xid == 0x5a5a5a5a5a5a5a5a) {
- CERROR("Reply received for freed request! Probably a missing "
- "ptlrpc_abort()\n");
- LBUG();
- }
-
- if (req->rq_xid != ev->match_bits) {
- CERROR("Reply packet for wrong request\n");
- LBUG();
- }
-
- if (ev->type == PTL_EVENT_PUT) {
- req->rq_repmsg = ev->mem_desc.start + ev->offset;
- barrier();
- wake_up(&req->rq_wait_for_rep);
- } else {
- // XXX make sure we understand all events, including ACK's
- CERROR("Unknown event %d\n", ev->type);
- LBUG();
- }
-
- RETURN(1);
-}
-
-int request_in_callback(ptl_event_t *ev)
-{
- struct ptlrpc_request_buffer_desc *rqbd = ev->mem_desc.user_ptr;
- struct ptlrpc_service *service = rqbd->rqbd_service;
-
- /* requests always contiguous */
- LASSERT((ev->mem_desc.options & PTL_MD_IOV) == 0);
- /* we only enable puts */
- LASSERT(ev->type == PTL_EVENT_PUT);
- LASSERT(atomic_read(&service->srv_nrqbds_receiving) > 0);
- LASSERT(atomic_read(&rqbd->rqbd_refcount) > 0);
-
- if (ev->rlength != ev->mlength)
- CERROR("Warning: Possibly truncated rpc (%d/%d)\n",
- ev->mlength, ev->rlength);
-
- if (ptl_is_valid_handle(&ev->unlinked_me)) {
- /* This is the last request to be received into this
- * request buffer. We don't bump the refcount, since the
- * thread servicing this event is effectively taking over
- * portals' reference.
- */
-#warning ev->unlinked_me.nal_idx is not set properly in a callback
- LASSERT(ev->unlinked_me.handle_idx==rqbd->rqbd_me_h.handle_idx);
-
- /* we're off the air */
- /* we'll probably start dropping packets in portals soon */
- if (atomic_dec_and_test(&service->srv_nrqbds_receiving))
- CERROR("All request buffers busy\n");
- } else {
- /* +1 ref for service thread */
- atomic_inc(&rqbd->rqbd_refcount);
- }
-
- wake_up(&service->srv_waitq);
-
- return 0;
-}
-
-static int bulk_source_callback(ptl_event_t *ev)
-{
- struct ptlrpc_bulk_desc *desc = ev->mem_desc.user_ptr;
- struct ptlrpc_bulk_page *bulk;
- struct list_head *tmp;
- struct list_head *next;
- ENTRY;
-
- CDEBUG(D_NET, "got %s event %d\n",
- (ev->type == PTL_EVENT_SENT) ? "SENT" :
- (ev->type == PTL_EVENT_ACK) ? "ACK" : "UNEXPECTED", ev->type);
-
- LASSERT(ev->type == PTL_EVENT_SENT || ev->type == PTL_EVENT_ACK);
-
- LASSERT(atomic_read(&desc->bd_source_callback_count) > 0 &&
- atomic_read(&desc->bd_source_callback_count) <= 2);
-
- /* 1 fragment for each page always */
- LASSERT(ev->mem_desc.niov == desc->bd_page_count);
-
- if (atomic_dec_and_test(&desc->bd_source_callback_count)) {
- list_for_each_safe(tmp, next, &desc->bd_page_list) {
- bulk = list_entry(tmp, struct ptlrpc_bulk_page,
- bp_link);
-
- if (bulk->bp_cb != NULL)
- bulk->bp_cb(bulk);
- }
- desc->bd_flags |= PTL_BULK_FL_SENT;
- wake_up(&desc->bd_waitq);
- if (desc->bd_ptl_ev_hdlr != NULL)
- desc->bd_ptl_ev_hdlr(desc);
- }
-
- RETURN(0);
-}
-
-static int bulk_sink_callback(ptl_event_t *ev)
-{
- struct ptlrpc_bulk_desc *desc = ev->mem_desc.user_ptr;
- struct ptlrpc_bulk_page *bulk;
- struct list_head *tmp;
- struct list_head *next;
- ptl_size_t total = 0;
- ENTRY;
-
- if (ev->type == PTL_EVENT_PUT) {
- /* put with zero offset */
- LASSERT(ev->offset == 0);
- /* used iovs */
- LASSERT((ev->mem_desc.options & PTL_MD_IOV) != 0);
- /* 1 fragment for each page always */
- LASSERT(ev->mem_desc.niov == desc->bd_page_count);
-
- list_for_each_safe (tmp, next, &desc->bd_page_list) {
- bulk = list_entry(tmp, struct ptlrpc_bulk_page,
- bp_link);
-
- total += bulk->bp_buflen;
-
- if (bulk->bp_cb != NULL)
- bulk->bp_cb(bulk);
- }
-
- LASSERT(ev->mem_desc.length == total);
-
- desc->bd_flags |= PTL_BULK_FL_RCVD;
- wake_up(&desc->bd_waitq);
- if (desc->bd_ptl_ev_hdlr != NULL)
- desc->bd_ptl_ev_hdlr(desc);
- } else {
- CERROR("Unexpected event type!\n");
- LBUG();
- }
-
- RETURN(1);
-}
-
-int ptlrpc_init_portals(void)
-{
- int rc;
- ptl_handle_ni_t ni;
-
- /* Use the qswnal if it's there */
- if ((qswnal_nip = inter_module_get("kqswnal_ni")) != NULL)
- ni = *qswnal_nip;
- else if ((gmnal_nip = inter_module_get("kgmnal_ni")) != NULL)
- ni = *gmnal_nip;
- else if ((socknal_nip = inter_module_get("ksocknal_ni")) != NULL)
- ni = *socknal_nip;
- else if ((toenal_nip = inter_module_get("ktoenal_ni")) != NULL)
- ni = *toenal_nip;
- else {
- CERROR("get_ni failed: is a NAL module loaded?\n");
- return -EIO;
- }
-
- rc = PtlEQAlloc(ni, 1024, request_out_callback, &request_out_eq);
- if (rc != PTL_OK)
- CERROR("PtlEQAlloc failed: %d\n", rc);
-
- rc = PtlEQAlloc(ni, 1024, reply_out_callback, &reply_out_eq);
- if (rc != PTL_OK)
- CERROR("PtlEQAlloc failed: %d\n", rc);
-
- rc = PtlEQAlloc(ni, 1024, reply_in_callback, &reply_in_eq);
- if (rc != PTL_OK)
- CERROR("PtlEQAlloc failed: %d\n", rc);
-
- rc = PtlEQAlloc(ni, 1024, bulk_source_callback, &bulk_source_eq);
- if (rc != PTL_OK)
- CERROR("PtlEQAlloc failed: %d\n", rc);
-
- rc = PtlEQAlloc(ni, 1024, bulk_sink_callback, &bulk_sink_eq);
- if (rc != PTL_OK)
- CERROR("PtlEQAlloc failed: %d\n", rc);
-
- return rc;
-}
-
-void ptlrpc_exit_portals(void)
-{
- PtlEQFree(request_out_eq);
- PtlEQFree(reply_out_eq);
- PtlEQFree(reply_in_eq);
- PtlEQFree(bulk_source_eq);
- PtlEQFree(bulk_sink_eq);
-
- if (qswnal_nip != NULL)
- inter_module_put("kqswnal_ni");
- if (socknal_nip != NULL)
- inter_module_put("ksocknal_ni");
- if (gmnal_nip != NULL)
- inter_module_put("kgmnal_ni");
- if (toenal_nip != NULL)
- inter_module_put("ktoenal_ni");
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/lustre_lite.h>
-#include <linux/lprocfs_status.h>
-
-int rd_uuid(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- int len = 0;
- len += snprintf(page, count, "%s\n",
- ((struct obd_device*)data)->obd_uuid);
- return len;
-}
-
-struct lprocfs_vars status_var_nm_1[] = {
- {"status/uuid", rd_uuid, 0, 0},
- {0}
-};
-int rd_numrefs(char* page, char **start, off_t off, int count, int *eof,
- void *data)
-{
- struct obd_type* class = (struct obd_type*)data;
- int len = 0;
- len += snprintf(page, count, "%d\n", class->typ_refcnt);
- return len;
-}
-
-struct lprocfs_vars status_class_var[] = {
- {"status/num_refs", rd_numrefs, 0, 0},
- {0}
-};
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/obd_support.h>
-#include <linux/lustre_net.h>
-#include <linux/lustre_lib.h>
-#include <linux/obd.h>
-
-extern ptl_handle_eq_t request_out_eq, reply_in_eq, reply_out_eq,
- bulk_source_eq, bulk_sink_eq;
-
-static int ptl_send_buf(struct ptlrpc_request *request,
- struct ptlrpc_connection *conn, int portal)
-{
- int rc;
- ptl_process_id_t remote_id;
- ptl_handle_md_t md_h;
-
- LASSERT(conn);
-
- request->rq_req_md.user_ptr = request;
-
- switch (request->rq_type) {
- case PTL_RPC_MSG_REQUEST:
- request->rq_reqmsg->type = HTON__u32(request->rq_type);
- request->rq_req_md.start = request->rq_reqmsg;
- request->rq_req_md.length = request->rq_reqlen;
- request->rq_req_md.eventq = request_out_eq;
- break;
- case PTL_RPC_MSG_ERR:
- case PTL_RPC_MSG_REPLY:
- request->rq_repmsg->type = HTON__u32(request->rq_type);
- request->rq_req_md.start = request->rq_repmsg;
- request->rq_req_md.length = request->rq_replen;
- request->rq_req_md.eventq = reply_out_eq;
- break;
- default:
- LBUG();
- return -1; /* notreached */
- }
- request->rq_req_md.threshold = 1;
- request->rq_req_md.options = PTL_MD_OP_PUT;
- request->rq_req_md.user_ptr = request;
-
- rc = PtlMDBind(conn->c_peer.peer_ni, request->rq_req_md, &md_h);
- if (rc != 0) {
- CERROR("PtlMDBind failed: %d\n", rc);
- LBUG();
- return rc;
- }
-
- remote_id.nid = conn->c_peer.peer_nid;
- remote_id.pid = 0;
-
- CDEBUG(D_NET, "Sending %d bytes to portal %d, xid "LPD64"\n",
- request->rq_req_md.length, portal, request->rq_xid);
-
- if (!portal)
- LBUG();
- rc = PtlPut(md_h, PTL_NOACK_REQ, remote_id, portal, 0, request->rq_xid,
- 0, 0);
- if (rc != PTL_OK) {
- CERROR("PtlPut("LPU64", %d, "LPD64") failed: %d\n",
- remote_id.nid, portal, request->rq_xid, rc);
- PtlMDUnlink(md_h);
- }
-
- return rc;
-}
-
-static inline struct iovec *
-ptlrpc_get_bulk_iov (struct ptlrpc_bulk_desc *desc)
-{
- struct iovec *iov;
-
- if (desc->bd_page_count <= sizeof (desc->bd_iov)/sizeof (struct iovec))
- return (desc->bd_iov);
-
- OBD_ALLOC (iov, desc->bd_page_count * sizeof (struct iovec));
- if (iov == NULL)
- LBUG();
-
- return (iov);
-}
-
-static inline void
-ptlrpc_put_bulk_iov (struct ptlrpc_bulk_desc *desc, struct iovec *iov)
-{
- if (desc->bd_page_count <= sizeof (desc->bd_iov)/sizeof (struct iovec))
- return;
-
- OBD_FREE (iov, desc->bd_page_count * sizeof (struct iovec));
-}
-
-int ptlrpc_send_bulk(struct ptlrpc_bulk_desc *desc)
-{
- int rc;
- struct list_head *tmp, *next;
- ptl_process_id_t remote_id;
- __u32 xid = 0;
- struct iovec *iov;
- ENTRY;
-
- iov = ptlrpc_get_bulk_iov (desc);
- if (iov == NULL)
- RETURN (-ENOMEM);
-
- desc->bd_md.start = iov;
- desc->bd_md.niov = 0;
- desc->bd_md.length = 0;
- desc->bd_md.eventq = bulk_source_eq;
- desc->bd_md.threshold = 2; /* SENT and ACK */
- desc->bd_md.options = PTL_MD_OP_PUT | PTL_MD_IOV;
- desc->bd_md.user_ptr = desc;
-
- atomic_set(&desc->bd_source_callback_count, 2);
-
- list_for_each_safe(tmp, next, &desc->bd_page_list) {
- struct ptlrpc_bulk_page *bulk;
- bulk = list_entry(tmp, struct ptlrpc_bulk_page, bp_link);
-
- LASSERT(desc->bd_md.niov < desc->bd_page_count);
-
- if (desc->bd_md.niov == 0)
- xid = bulk->bp_xid;
- LASSERT(xid == bulk->bp_xid); /* should all be the same */
-
- iov[desc->bd_md.niov].iov_base = bulk->bp_buf;
- iov[desc->bd_md.niov].iov_len = bulk->bp_buflen;
- desc->bd_md.niov++;
- desc->bd_md.length += bulk->bp_buflen;
- }
-
- LASSERT(desc->bd_md.niov == desc->bd_page_count);
- LASSERT(desc->bd_md.niov != 0);
-
- rc = PtlMDBind(desc->bd_connection->c_peer.peer_ni, desc->bd_md,
- &desc->bd_md_h);
-
- ptlrpc_put_bulk_iov (desc, iov); /*move down to reduce latency to send*/
-
- if (rc != PTL_OK) {
- CERROR("PtlMDBind failed: %d\n", rc);
- LBUG();
- RETURN(rc);
- }
-
- remote_id.nid = desc->bd_connection->c_peer.peer_nid;
- remote_id.pid = 0;
-
- CDEBUG(D_NET, "Sending %u pages %u bytes to portal %d nid "LPX64" pid "
- "%d xid %d\n", desc->bd_md.niov, desc->bd_md.length,
- desc->bd_portal, remote_id.nid, remote_id.pid, xid);
-
- rc = PtlPut(desc->bd_md_h, PTL_ACK_REQ, remote_id,
- desc->bd_portal, 0, xid, 0, 0);
- if (rc != PTL_OK) {
- CERROR("PtlPut("LPU64", %d, %d) failed: %d\n",
- remote_id.nid, desc->bd_portal, xid, rc);
- PtlMDUnlink(desc->bd_md_h);
- LBUG();
- RETURN(rc);
- }
-
- RETURN(0);
-}
-
-int ptlrpc_register_bulk(struct ptlrpc_bulk_desc *desc)
-{
- struct list_head *tmp, *next;
- int rc;
- __u32 xid = 0;
- struct iovec *iov;
- ptl_process_id_t source_id;
- ENTRY;
-
- if (desc->bd_page_count > PTL_MD_MAX_IOV) {
- CERROR("iov longer than %d pages not supported (count=%d)\n",
- PTL_MD_MAX_IOV, desc->bd_page_count);
- RETURN(-EINVAL);
- }
-
- iov = ptlrpc_get_bulk_iov (desc);
- if (iov == NULL)
- return (-ENOMEM);
-
- desc->bd_md.start = iov;
- desc->bd_md.niov = 0;
- desc->bd_md.length = 0;
- desc->bd_md.threshold = 1;
- desc->bd_md.options = PTL_MD_OP_PUT | PTL_MD_IOV;
- desc->bd_md.user_ptr = desc;
- desc->bd_md.eventq = bulk_sink_eq;
-
- list_for_each_safe(tmp, next, &desc->bd_page_list) {
- struct ptlrpc_bulk_page *bulk;
- bulk = list_entry(tmp, struct ptlrpc_bulk_page, bp_link);
-
- LASSERT(desc->bd_md.niov < desc->bd_page_count);
-
- if (desc->bd_md.niov == 0)
- xid = bulk->bp_xid;
- LASSERT(xid == bulk->bp_xid); /* should all be the same */
-
- iov[desc->bd_md.niov].iov_base = bulk->bp_buf;
- iov[desc->bd_md.niov].iov_len = bulk->bp_buflen;
- desc->bd_md.niov++;
- desc->bd_md.length += bulk->bp_buflen;
- }
-
- LASSERT(desc->bd_md.niov == desc->bd_page_count);
- LASSERT(desc->bd_md.niov != 0);
-
- source_id.nid = desc->bd_connection->c_peer.peer_nid;
- source_id.pid = PTL_PID_ANY;
-
- rc = PtlMEAttach(desc->bd_connection->c_peer.peer_ni,
- desc->bd_portal, source_id, xid, 0,
- PTL_UNLINK, PTL_INS_AFTER, &desc->bd_me_h);
-
- if (rc != PTL_OK) {
- CERROR("PtlMEAttach failed: %d\n", rc);
- LBUG();
- GOTO(cleanup, rc);
- }
-
- rc = PtlMDAttach(desc->bd_me_h, desc->bd_md, PTL_UNLINK,
- &desc->bd_md_h);
- if (rc != PTL_OK) {
- CERROR("PtlMDAttach failed: %d\n", rc);
- LBUG();
- GOTO(cleanup, rc);
- }
-
- ptlrpc_put_bulk_iov (desc, iov);
-
- CDEBUG(D_NET, "Setup bulk sink buffers: %u pages %u bytes, xid %u, "
- "portal %u\n", desc->bd_md.niov, desc->bd_md.length,
- xid, desc->bd_portal);
-
- RETURN(0);
-
- cleanup:
- ptlrpc_put_bulk_iov (desc, iov);
- ptlrpc_abort_bulk(desc);
-
- return rc;
-}
-
-int ptlrpc_abort_bulk(struct ptlrpc_bulk_desc *desc)
-{
- /* This should be safe: these handles are initialized to be
- * invalid in ptlrpc_prep_bulk() */
- PtlMDUnlink(desc->bd_md_h);
- PtlMEUnlink(desc->bd_me_h);
-
- return 0;
-}
-
-void obd_brw_set_add(struct obd_brw_set *set, struct ptlrpc_bulk_desc *desc)
-{
- atomic_inc(&desc->bd_refcount);
- atomic_inc(&set->brw_refcount);
- desc->bd_brw_set = set;
- list_add(&desc->bd_set_chain, &set->brw_desc_head);
-}
-
-struct obd_brw_set *obd_brw_set_new(void)
-{
- struct obd_brw_set *set;
-
- OBD_ALLOC(set, sizeof(*set));
-
- if (set != NULL) {
- init_waitqueue_head(&set->brw_waitq);
- INIT_LIST_HEAD(&set->brw_desc_head);
- atomic_set(&set->brw_refcount, 0);
- }
-
- return set;
-}
-
-void obd_brw_set_free(struct obd_brw_set *set)
-{
- struct list_head *tmp, *next;
- ENTRY;
-
- if (!list_empty(&set->brw_desc_head)) {
- EXIT;
- return;
- }
-
- list_for_each_safe(tmp, next, &set->brw_desc_head) {
- struct ptlrpc_bulk_desc *desc =
- list_entry(tmp, struct ptlrpc_bulk_desc, bd_set_chain);
-
- CERROR("Unfinished bulk descriptor: %p\n", desc);
-
- ptlrpc_abort_bulk(desc);
- }
- OBD_FREE(set, sizeof(*set));
- EXIT;
- return;
-}
-
-int ptlrpc_reply(struct ptlrpc_service *svc, struct ptlrpc_request *req)
-{
- if (req->rq_repmsg == NULL) {
- CERROR("bad: someone called ptlrpc_reply when they meant "
- "ptlrpc_error\n");
- return -EINVAL;
- }
-
- /* FIXME: we need to increment the count of handled events */
- if (req->rq_type != PTL_RPC_MSG_ERR)
- req->rq_type = PTL_RPC_MSG_REPLY;
- //req->rq_repmsg->conn = req->rq_connection->c_remote_conn;
- //req->rq_repmsg->token = req->rq_connection->c_remote_token;
- req->rq_repmsg->status = HTON__u32(req->rq_status);
- return ptl_send_buf(req, req->rq_connection, svc->srv_rep_portal);
-}
-
-int ptlrpc_error(struct ptlrpc_service *svc, struct ptlrpc_request *req)
-{
- int rc;
- ENTRY;
-
- if (req->rq_repmsg) {
- CERROR("req already has repmsg\n");
- LBUG();
- }
-
- rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
-
- req->rq_type = PTL_RPC_MSG_ERR;
-
- rc = ptlrpc_reply(svc, req);
- RETURN(rc);
-}
-
-int ptl_send_rpc(struct ptlrpc_request *request)
-{
- int rc;
- char *repbuf;
- ptl_process_id_t source_id;
-
- ENTRY;
-
- if (request->rq_type != PTL_RPC_MSG_REQUEST) {
- CERROR("wrong packet type sent %d\n",
- NTOH__u32(request->rq_reqmsg->type));
- LBUG();
- RETURN(EINVAL);
- }
-
- source_id.nid = request->rq_connection->c_peer.peer_nid;
- source_id.pid = PTL_PID_ANY;
-
- /* add a ref, which will be balanced in request_out_callback */
- atomic_inc(&request->rq_refcount);
- if (request->rq_replen != 0) {
- /* request->rq_repmsg is set only when the reply comes in, in
- * client_packet_callback() */
- if (request->rq_reply_md.start) {
- PtlMEUnlink(request->rq_reply_me_h);
- OBD_FREE(request->rq_reply_md.start,
- request->rq_replen);
- /* If we're resending, rq_repmsg needs to be NULLed out
- * again so that ptlrpc_check_reply doesn't trip early.
- */
- request->rq_repmsg = NULL;
- }
- OBD_ALLOC(repbuf, request->rq_replen);
- if (!repbuf) {
- LBUG();
- RETURN(ENOMEM);
- }
-
- rc = PtlMEAttach(request->rq_connection->c_peer.peer_ni,
- request->rq_reply_portal,/* XXX FIXME bug 625069 */
- source_id, request->rq_xid, 0, PTL_UNLINK,
- PTL_INS_AFTER, &request->rq_reply_me_h);
- if (rc != PTL_OK) {
- CERROR("PtlMEAttach failed: %d\n", rc);
- LBUG();
- GOTO(cleanup, rc);
- }
-
- request->rq_reply_md.start = repbuf;
- request->rq_reply_md.length = request->rq_replen;
- request->rq_reply_md.threshold = 1;
- request->rq_reply_md.options = PTL_MD_OP_PUT;
- request->rq_reply_md.user_ptr = request;
- request->rq_reply_md.eventq = reply_in_eq;
-
- rc = PtlMDAttach(request->rq_reply_me_h, request->rq_reply_md,
- PTL_UNLINK, NULL);
- if (rc != PTL_OK) {
- CERROR("PtlMDAttach failed: %d\n", rc);
- LBUG();
- GOTO(cleanup2, rc);
- }
-
- CDEBUG(D_NET, "Setup reply buffer: %u bytes, xid "LPU64
- ", portal %u\n",
- request->rq_replen, request->rq_xid,
- request->rq_reply_portal);
- }
-
- /* Clear any flags that may be present from previous sends,
- * except for REPLAY. */
- request->rq_flags &= PTL_RPC_FL_REPLAY;
- rc = ptl_send_buf(request, request->rq_connection,
- request->rq_request_portal);
- RETURN(rc);
-
- cleanup2:
- PtlMEUnlink(request->rq_reply_me_h);
- cleanup:
- OBD_FREE(repbuf, request->rq_replen);
- // up(&request->rq_client->cli_rpc_sem);
-
- return rc;
-}
-
-void ptlrpc_link_svc_me(struct ptlrpc_request_buffer_desc *rqbd)
-{
- struct ptlrpc_service *service = rqbd->rqbd_service;
- static ptl_process_id_t match_id = {PTL_NID_ANY, PTL_PID_ANY};
- int rc;
- ptl_md_t dummy;
- ptl_handle_md_t md_h;
-
- LASSERT(atomic_read(&rqbd->rqbd_refcount) == 0);
-
- /* Attach the leading ME on which we build the ring */
- rc = PtlMEAttach(service->srv_self.peer_ni, service->srv_req_portal,
- match_id, 0, ~0,
- PTL_UNLINK, PTL_INS_AFTER, &rqbd->rqbd_me_h);
- if (rc != PTL_OK) {
- CERROR("PtlMEAttach failed: %d\n", rc);
- LBUG();
- }
-
- dummy.start = rqbd->rqbd_buffer;
- dummy.length = service->srv_buf_size;
- dummy.max_size = service->srv_max_req_size;
- dummy.threshold = PTL_MD_THRESH_INF;
- dummy.options = PTL_MD_OP_PUT | PTL_MD_MAX_SIZE | PTL_MD_AUTO_UNLINK;
- dummy.user_ptr = rqbd;
- dummy.eventq = service->srv_eq_h;
-
- atomic_inc(&service->srv_nrqbds_receiving);
- atomic_set(&rqbd->rqbd_refcount, 1); /* 1 ref for portals */
-
- rc = PtlMDAttach(rqbd->rqbd_me_h, dummy, PTL_UNLINK, &md_h);
- if (rc != PTL_OK) {
- CERROR("PtlMDAttach failed: %d\n", rc);
- LBUG();
-#warning proper cleanup required
- PtlMEUnlink (rqbd->rqbd_me_h);
- atomic_set(&rqbd->rqbd_refcount, 0);
- atomic_dec(&service->srv_nrqbds_receiving);
- }
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * (Un)packing of OST requests
- *
- */
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/obd_support.h>
-#include <linux/lustre_net.h>
-
-int lustre_pack_msg(int count, int *lens, char **bufs, int *len,
- struct lustre_msg **msg)
-{
- char *ptr;
- struct lustre_msg *m;
- int size = 0, i;
-
- for (i = 0; i < count; i++)
- size += size_round(lens[i]);
-
- *len = size_round(sizeof(*m) + count * sizeof(__u32)) + size;
-
- OBD_ALLOC(*msg, *len);
- if (!*msg)
- RETURN(-ENOMEM);
-
- m = *msg;
- m->bufcount = HTON__u32(count);
- for (i = 0; i < count; i++)
- m->buflens[i] = HTON__u32(lens[i]);
-
- ptr = (char *)m + size_round(sizeof(*m) + count * sizeof(__u32));
- for (i = 0; i < count; i++) {
- char *tmp = NULL;
- if (bufs)
- tmp = bufs[i];
- LOGL(tmp, lens[i], ptr);
- }
-
- return 0;
-}
-
-/* This returns the size of the buffer that is required to hold a lustre_msg
- * with the given sub-buffer lengths. */
-int lustre_msg_size(int count, int *lengths)
-{
- int size = 0, i;
-
- for (i = 0; i < count; i++)
- size += size_round(lengths[i]);
-
- size += size_round(sizeof(struct lustre_msg) + count * sizeof(__u32));
-
- return size;
-}
-
-int lustre_unpack_msg(struct lustre_msg *m, int len)
-{
- int required_len, i;
- ENTRY;
-
- required_len = size_round(sizeof(*m));
- if (len < required_len)
- RETURN(-EINVAL);
-
- m->opc = NTOH__u32(m->opc);
- m->status = NTOH__u32(m->status);
- m->type = NTOH__u32(m->type);
- m->bufcount = NTOH__u32(m->bufcount);
- m->last_xid = NTOH__u64(m->last_xid);
- m->last_committed = NTOH__u64(m->last_committed);
-
- required_len = size_round(sizeof(*m) + m->bufcount * sizeof(__u32));
- if (len < required_len)
- RETURN(-EINVAL);
-
- for (i = 0; i < m->bufcount; i++) {
- m->buflens[i] = NTOH__u32(m->buflens[i]);
- required_len += size_round(m->buflens[i]);
- }
-
- if (len < required_len) {
- CERROR("len: %d, required_len %d\n", len, required_len);
- RETURN(-EINVAL);
- }
-
- RETURN(0);
-}
-
-void *lustre_msg_buf(struct lustre_msg *m, int n)
-{
- int i, offset;
-
- if (!m) {
- CERROR("no message buffer!\n");
- LBUG();
- return NULL;
- }
-
- if (n < 0 || n >= m->bufcount) {
- CERROR("referencing bad sub buffer in %p (want %d, count %d)!\n",
- m, n, m->bufcount);
- LBUG();
- return NULL;
- }
-
- if (m->buflens[n] == 0) {
- CERROR("zero-length buffer requested for buffer %d in %p\n", n,
- m);
- return NULL;
- }
-
- offset = size_round(sizeof(*m) + m->bufcount * sizeof(__u32));
-
- for (i = 0; i < n; i++)
- offset += size_round(m->buflens[i]);
-
- return (char *)m + offset;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * obd/rpc/recovd.c
- *
- * Lustre High Availability Daemon
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * by Peter Braam <braam@clusterfs.com>
- *
- */
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/lustre_lite.h>
-#include <linux/lustre_ha.h>
-#include <linux/obd_support.h>
-
-/* dump_connection_list, but shorter for nicer debugging logs */
-static void d_c_l(struct list_head *head)
-{
- int sanity = 0;
- struct list_head *tmp;
-
- list_for_each(tmp, head) {
- struct ptlrpc_connection *conn =
- list_entry(tmp, struct ptlrpc_connection,
- c_recovd_data.rd_managed_chain);
- CDEBUG(D_HA, " %p = %s (%d/%d)\n", conn, conn->c_remote_uuid,
- conn->c_recovd_data.rd_phase,
- conn->c_recovd_data.rd_next_phase);
- if (sanity++ > 1000)
- LBUG();
- }
-}
-
-static void dump_lists(struct recovd_obd *recovd)
-{
- CDEBUG(D_HA, "managed: \n");
- d_c_l(&recovd->recovd_managed_items);
- CDEBUG(D_HA, "troubled: \n");
- d_c_l(&recovd->recovd_troubled_items);
-}
-
-void recovd_conn_manage(struct ptlrpc_connection *conn,
- struct recovd_obd *recovd, ptlrpc_recovery_cb_t recover)
-{
- struct recovd_data *rd = &conn->c_recovd_data;
- ENTRY;
- if (!recovd || !recover) {
- EXIT;
- return;
- }
-
- if (!list_empty(&rd->rd_managed_chain)) {
- if (rd->rd_recovd == recovd && rd->rd_recover == recover) {
- CDEBUG(D_HA, "conn %p/%s already setup for recovery\n",
- conn, conn->c_remote_uuid);
- EXIT;
- return;
- }
- CDEBUG(D_HA,
- "conn %p/%s has recovery items %p/%p, making %p/%p\n",
- conn, conn->c_remote_uuid, rd->rd_recovd, rd->rd_recover,
- recovd, recover);
- spin_lock(&rd->rd_recovd->recovd_lock);
- list_del_init(&rd->rd_managed_chain);
- spin_unlock(&rd->rd_recovd->recovd_lock);
- }
-
- rd->rd_recovd = recovd;
- rd->rd_recover = recover;
- rd->rd_phase = RD_IDLE;
- rd->rd_next_phase = RD_TROUBLED;
-
- spin_lock(&recovd->recovd_lock);
- list_add(&rd->rd_managed_chain, &recovd->recovd_managed_items);
- dump_lists(recovd);
- spin_unlock(&recovd->recovd_lock);
-
- EXIT;
-}
-
-void recovd_conn_unmanage(struct ptlrpc_connection *conn)
-{
- struct recovd_data *rd = &conn->c_recovd_data;
- struct recovd_obd *recovd = rd->rd_recovd;
- ENTRY;
-
- if (recovd) {
- spin_lock(&recovd->recovd_lock);
- list_del_init(&rd->rd_managed_chain);
- rd->rd_recovd = NULL;
- spin_unlock(&recovd->recovd_lock);
- }
- /* should be safe enough, right? */
- rd->rd_recover = NULL;
- rd->rd_next_phase = RD_IDLE;
- rd->rd_next_phase = RD_TROUBLED;
-}
-
-void recovd_conn_fail(struct ptlrpc_connection *conn)
-{
- struct recovd_data *rd = &conn->c_recovd_data;
- struct recovd_obd *recovd = rd->rd_recovd;
- ENTRY;
-
- if (!recovd) {
- CERROR("no recovd for connection %p\n", conn);
- EXIT;
- return;
- }
-
- spin_lock(&recovd->recovd_lock);
- if (rd->rd_phase == RD_TROUBLED || rd->rd_phase == RD_PREPARING) {
- CDEBUG(D_HA, "connection %p to %s already in recovery\n",
- conn, conn->c_remote_uuid);
- spin_unlock(&recovd->recovd_lock);
- EXIT;
- return;
- }
-
- CERROR("connection %p to %s (%08x %08lx %08lx) failed\n", conn,
- conn->c_remote_uuid, conn->c_peer.peer_nid,
- conn->c_peer.peer_ni.nal_idx, conn->c_peer.peer_ni.handle_idx);
- list_del(&rd->rd_managed_chain);
- list_add_tail(&rd->rd_managed_chain, &recovd->recovd_troubled_items);
- if (rd->rd_phase != RD_IDLE) {
- CDEBUG(D_HA,
- "connection %p to %s failed in recovery: restarting\n",
- conn, conn->c_remote_uuid);
- /* XXX call callback with PHASE_FAILED? */
- rd->rd_next_phase = RD_TROUBLED;
- }
- rd->rd_phase = RD_TROUBLED;
- dump_lists(recovd);
- spin_unlock(&recovd->recovd_lock);
-
- wake_up(&recovd->recovd_waitq);
-
- EXIT;
-}
-
-void recovd_conn_fixed(struct ptlrpc_connection *conn)
-{
- struct recovd_data *rd = &conn->c_recovd_data;
- ENTRY;
-
- CDEBUG(D_HA, "connection %p (now to %s) fixed\n",
- conn, conn->c_remote_uuid);
- spin_lock(&rd->rd_recovd->recovd_lock);
- list_del(&rd->rd_managed_chain);
- rd->rd_phase = RD_IDLE;
- rd->rd_next_phase = RD_TROUBLED;
- list_add(&rd->rd_managed_chain, &rd->rd_recovd->recovd_managed_items);
- dump_lists(rd->rd_recovd);
- spin_unlock(&rd->rd_recovd->recovd_lock);
-
- EXIT;
-}
-
-static int recovd_check_event(struct recovd_obd *recovd)
-{
- int rc = 0;
- struct list_head *tmp;
-
- ENTRY;
-
- spin_lock(&recovd->recovd_lock);
-
- if (recovd->recovd_state == RECOVD_STOPPING)
- GOTO(out, rc = 1);
-
- list_for_each(tmp, &recovd->recovd_troubled_items) {
-
- struct recovd_data *rd = list_entry(tmp, struct recovd_data,
- rd_managed_chain);
-
- if (rd->rd_phase == rd->rd_next_phase ||
- rd->rd_phase == RD_FAILED)
- GOTO(out, rc = 1);
- }
-
- out:
- spin_unlock(&recovd->recovd_lock);
- RETURN(rc);
-}
-
-static int recovd_handle_event(struct recovd_obd *recovd)
-{
- struct list_head *tmp, *n;
- int rc = 0;
- ENTRY;
-
- spin_lock(&recovd->recovd_lock);
-
- dump_lists(recovd);
-
- /*
- * We use _safe here because one of the callbacks, expecially
- * FAILURE or PREPARED, could move list items around.
- */
- list_for_each_safe(tmp, n, &recovd->recovd_troubled_items) {
- struct recovd_data *rd = list_entry(tmp, struct recovd_data,
- rd_managed_chain);
-
- if (rd->rd_phase != RD_FAILED &&
- rd->rd_phase != rd->rd_next_phase)
- continue;
-
- switch (rd->rd_phase) {
- case RD_FAILED:
- cb_failed: /* must always reach here with recovd_lock held! */
- CERROR("recovery FAILED for rd %p (conn %p): %d\n",
- rd, class_rd2conn(rd), rc);
-
- spin_unlock(&recovd->recovd_lock);
- (void)rd->rd_recover(rd, PTLRPC_RECOVD_PHASE_FAILURE);
- spin_lock(&recovd->recovd_lock);
- break;
-
- case RD_TROUBLED:
- if (!rd->rd_recover) {
- CERROR("no rd_recover for rd %p (conn %p)\n",
- rd, class_rd2conn(rd));
- rc = -EINVAL;
- break;
- }
- CERROR("starting recovery for rd %p (conn %p)\n",
- rd, class_rd2conn(rd));
- rd->rd_phase = RD_PREPARING;
- rd->rd_next_phase = RD_PREPARED;
-
- spin_unlock(&recovd->recovd_lock);
- rc = rd->rd_recover(rd, PTLRPC_RECOVD_PHASE_PREPARE);
- spin_lock(&recovd->recovd_lock);
- if (rc)
- goto cb_failed;
-
- break;
-
- case RD_PREPARED:
-
- CERROR("recovery prepared for rd %p (conn %p)\n",
- rd, class_rd2conn(rd));
- rd->rd_phase = RD_RECOVERING;
- rd->rd_next_phase = RD_RECOVERED;
-
- spin_unlock(&recovd->recovd_lock);
- rc = rd->rd_recover(rd, PTLRPC_RECOVD_PHASE_RECOVER);
- spin_lock(&recovd->recovd_lock);
- if (rc)
- goto cb_failed;
-
- break;
-
- case RD_RECOVERED:
- rd->rd_phase = RD_IDLE;
- rd->rd_next_phase = RD_TROUBLED;
-
- CERROR("recovery complete for rd %p (conn %p)\n",
- rd, class_rd2conn(rd));
- break;
-
- default:
- break;
- }
- }
- spin_unlock(&recovd->recovd_lock);
- RETURN(0);
-}
-
-static int recovd_main(void *arg)
-{
- struct recovd_obd *recovd = (struct recovd_obd *)arg;
-
- ENTRY;
-
- lock_kernel();
- daemonize();
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- sigfillset(¤t->blocked);
- recalc_sigpending();
-#else
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
-#endif
-
- sprintf(current->comm, "lustre_recovd");
- unlock_kernel();
-
- /* Signal that the thread is running. */
- recovd->recovd_thread = current;
- recovd->recovd_state = RECOVD_READY;
- wake_up(&recovd->recovd_ctl_waitq);
-
- /* And now, loop forever on requests. */
- while (1) {
- wait_event(recovd->recovd_waitq, recovd_check_event(recovd));
- if (recovd->recovd_state == RECOVD_STOPPING)
- break;
- recovd_handle_event(recovd);
- }
-
- recovd->recovd_thread = NULL;
- recovd->recovd_state = RECOVD_STOPPED;
- wake_up(&recovd->recovd_ctl_waitq);
- CDEBUG(D_HA, "mgr exiting process %d\n", current->pid);
- RETURN(0);
-}
-
-int recovd_setup(struct recovd_obd *recovd)
-{
- int rc;
-
- ENTRY;
-
- INIT_LIST_HEAD(&recovd->recovd_managed_items);
- INIT_LIST_HEAD(&recovd->recovd_troubled_items);
- spin_lock_init(&recovd->recovd_lock);
-
- init_waitqueue_head(&recovd->recovd_waitq);
- init_waitqueue_head(&recovd->recovd_recovery_waitq);
- init_waitqueue_head(&recovd->recovd_ctl_waitq);
-
- rc = kernel_thread(recovd_main, (void *)recovd,
- CLONE_VM | CLONE_FS | CLONE_FILES);
- if (rc < 0) {
- CERROR("cannot start thread\n");
- RETURN(-EINVAL);
- }
- wait_event(recovd->recovd_ctl_waitq,
- recovd->recovd_state == RECOVD_READY);
-
- ptlrpc_recovd = recovd;
- class_signal_connection_failure = recovd_conn_fail;
-
- RETURN(0);
-}
-
-int recovd_cleanup(struct recovd_obd *recovd)
-{
- ENTRY;
- spin_lock(&recovd->recovd_lock);
- recovd->recovd_state = RECOVD_STOPPING;
- wake_up(&recovd->recovd_waitq);
- spin_unlock(&recovd->recovd_lock);
-
- wait_event(recovd->recovd_ctl_waitq,
- (recovd->recovd_state == RECOVD_STOPPED));
- RETURN(0);
-}
-
-struct recovd_obd *ptlrpc_recovd;
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Portal-RPC reconnection and replay operations, for use in recovery.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copyright (C) 1996 Peter J. Braam <braam@stelias.com>
- * Copyright (C) 1999 Stelias Computing Inc. <braam@stelias.com>
- * Copyright (C) 1999 Seagate Technology Inc.
- * Copyright (C) 2001 Mountain View Data, Inc.
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kmod.h>
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/lustre_ha.h>
-#include <linux/lustre_net.h>
-#include <linux/obd.h>
-
-int ptlrpc_reconnect_import(struct obd_import *imp, int rq_opc)
-{
- struct obd_device *obd = imp->imp_obd;
- struct client_obd *cli = &obd->u.cli;
- int size[] = { sizeof(cli->cl_target_uuid), sizeof(obd->obd_uuid) };
- char *tmp[] = {cli->cl_target_uuid, obd->obd_uuid };
- struct ptlrpc_connection *conn = imp->imp_connection;
- struct lustre_handle old_hdl;
- struct ptlrpc_request *request;
- struct obd_export *ldlmexp;
- int rc;
-
- request = ptlrpc_prep_req(imp, rq_opc, 2, size, tmp);
- request->rq_level = LUSTRE_CONN_NEW;
- request->rq_replen = lustre_msg_size(0, NULL);
- /*
- * This address is the export that represents our client-side LDLM
- * service (for ASTs). We should only have one on this list, so we
- * just grab the first one.
- *
- * XXX tear down export, call class_obd_connect?
- */
- ldlmexp = list_entry(obd->obd_exports.next, struct obd_export,
- exp_obd_chain);
- request->rq_reqmsg->addr = (__u64)(unsigned long)ldlmexp;
- request->rq_reqmsg->cookie = ldlmexp->exp_cookie;
- rc = ptlrpc_queue_wait(request);
- switch (rc) {
- case EALREADY:
- case -EALREADY:
- /* already connected! */
- memset(&old_hdl, 0, sizeof(old_hdl));
- if (!memcmp(&old_hdl.addr, &request->rq_repmsg->addr,
- sizeof (old_hdl.addr)) &&
- !memcmp(&old_hdl.cookie, &request->rq_repmsg->cookie,
- sizeof (old_hdl.cookie))) {
- CERROR("%s@%s didn't like our handle %Lx/%Lx, failed\n",
- cli->cl_target_uuid, conn->c_remote_uuid,
- (__u64)(unsigned long)ldlmexp,
- ldlmexp->exp_cookie);
- GOTO(out_disc, rc = -ENOTCONN);
- }
-
- old_hdl.addr = request->rq_repmsg->addr;
- old_hdl.cookie = request->rq_repmsg->cookie;
- if (memcmp(&imp->imp_handle, &old_hdl, sizeof(old_hdl))) {
- CERROR("%s@%s changed handle from %Lx/%Lx to %Lx/%Lx; "
- "copying, but this may foreshadow disaster\n",
- cli->cl_target_uuid, conn->c_remote_uuid,
- old_hdl.addr, old_hdl.cookie,
- imp->imp_handle.addr, imp->imp_handle.cookie);
- imp->imp_handle.addr = request->rq_repmsg->addr;
- imp->imp_handle.cookie = request->rq_repmsg->cookie;
- GOTO(out_disc, rc = EALREADY);
- }
-
- CERROR("reconnected to %s@%s after partition\n",
- cli->cl_target_uuid, conn->c_remote_uuid);
- GOTO(out_disc, rc = EALREADY);
- case 0:
- old_hdl = imp->imp_handle;
- imp->imp_handle.addr = request->rq_repmsg->addr;
- imp->imp_handle.cookie = request->rq_repmsg->cookie;
- CERROR("now connected to %s@%s (%Lx/%Lx, was %Lx/%Lx)!\n",
- cli->cl_target_uuid, conn->c_remote_uuid,
- imp->imp_handle.addr, imp->imp_handle.cookie,
- old_hdl.addr, old_hdl.cookie);
- GOTO(out_disc, rc = 0);
- default:
- CERROR("cannot connect to %s@%s: rc = %d\n",
- cli->cl_target_uuid, conn->c_remote_uuid, rc);
- GOTO(out_disc, rc = -ENOTCONN); /* XXX preserve rc? */
- }
-
- out_disc:
- ptlrpc_req_finished(request);
- return rc;
-}
-
-int ptlrpc_run_recovery_upcall(struct ptlrpc_connection *conn)
-{
- char *argv[3];
- char *envp[3];
- int rc;
-
- ENTRY;
- argv[0] = obd_recovery_upcall;
- argv[1] = conn->c_remote_uuid;
- argv[2] = NULL;
-
- envp[0] = "HOME=/";
- envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
- envp[2] = NULL;
-
- rc = call_usermodehelper(argv[0], argv, envp);
- if (rc < 0) {
- CERROR("Error invoking recovery upcall %s for %s: %d\n",
- argv[0], argv[1], rc);
- CERROR("Check /proc/sys/lustre/recovery_upcall?\n");
- } else {
- CERROR("Invoked upcall %s for connection %s\n",
- argv[0], argv[1]);
- }
-
- /*
- * We don't want to make this a "failed" recovery, because the system
- * administrator -- or, perhaps, tester -- may well be able to rescue
- * things by running the correct upcall.
- */
- RETURN(0);
-}
-
-int ptlrpc_replay(struct obd_import *imp, int send_last_flag)
-{
- int rc = 0;
- struct list_head *tmp, *pos;
- struct ptlrpc_request *req;
- __u64 committed = imp->imp_peer_committed_transno;
- ENTRY;
-
- /* It might have committed some after we last spoke, so make sure we
- * get rid of them now.
- */
- spin_lock(&imp->imp_lock);
-
- ptlrpc_free_committed(imp);
-
- CDEBUG(D_HA, "import %p from %s has committed "LPD64"\n",
- imp, imp->imp_obd->u.cli.cl_target_uuid, committed);
-
- list_for_each(tmp, &imp->imp_replay_list) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
- DEBUG_REQ(D_HA, req, "RETAINED: ");
- }
-
- list_for_each_safe(tmp, pos, &imp->imp_replay_list) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
-
- if (req->rq_transno == imp->imp_max_transno &&
- send_last_flag) {
- req->rq_reqmsg->flags |= MSG_LAST_REPLAY;
- DEBUG_REQ(D_HA, req, "LAST_REPLAY:");
- } else {
- DEBUG_REQ(D_HA, req, "REPLAY:");
- }
-
- rc = ptlrpc_replay_req(req);
- req->rq_reqmsg->flags &= ~MSG_LAST_REPLAY;
-
- if (rc) {
- CERROR("recovery replay error %d for req %Ld\n",
- rc, req->rq_xid);
- GOTO(out, rc);
- }
- }
-
- out:
- spin_unlock(&imp->imp_lock);
- return rc;
-}
-
-#define NO_RESEND 0 /* No action required. */
-#define RESEND 1 /* Resend required. */
-#define RESEND_IGNORE 2 /* Resend, ignore the reply (already saw it). */
-#define RESTART 3 /* Have to restart the call, sorry! */
-
-static int resend_type(struct ptlrpc_request *req, __u64 committed)
-{
- if (req->rq_transno < committed) {
- if (req->rq_flags & PTL_RPC_FL_REPLIED) {
- /* Saw the reply and it was committed, no biggie. */
- DEBUG_REQ(D_HA, req, "NO_RESEND");
- return NO_RESEND;
- }
- /* Request committed, but no reply: have to restart. */
- return RESTART;
- }
-
- if (req->rq_flags & PTL_RPC_FL_REPLIED) {
- /* Saw reply, so resend and ignore new reply. */
- return RESEND_IGNORE;
- }
-
- /* Didn't see reply either, so resend. */
- return RESEND;
-
-}
-
-int ptlrpc_resend(struct obd_import *imp)
-{
- int rc = 0;
- struct list_head *tmp, *pos;
- struct ptlrpc_request *req;
- __u64 committed = imp->imp_peer_committed_transno;
-
- ENTRY;
-
- spin_lock(&imp->imp_lock);
- list_for_each(tmp, &imp->imp_sending_list) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
- DEBUG_REQ(D_HA, req, "SENDING: ");
- }
-
- list_for_each_safe(tmp, pos, &imp->imp_sending_list) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
-
- switch(resend_type(req, committed)) {
- case NO_RESEND:
- break;
-
- case RESTART:
- DEBUG_REQ(D_HA, req, "RESTART:");
- ptlrpc_restart_req(req);
- break;
-
- case RESEND_IGNORE:
- DEBUG_REQ(D_HA, req, "RESEND_IGNORE:");
- rc = ptlrpc_replay_req(req);
- if (rc) {
- DEBUG_REQ(D_ERROR, req, "error %d resending:",
- rc);
- ptlrpc_restart_req(req); /* might as well */
- }
- break;
-
- case RESEND:
- DEBUG_REQ(D_HA, req, "RESEND:");
- ptlrpc_resend_req(req);
- break;
-
- default:
- LBUG();
- }
- }
-
- RETURN(rc);
-}
-
-void ptlrpc_wake_delayed(struct obd_import *imp)
-{
- struct list_head *tmp, *pos;
- struct ptlrpc_request *req;
-
- spin_lock(&imp->imp_lock);
- list_for_each_safe(tmp, pos, &imp->imp_delayed_list) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
- DEBUG_REQ(D_HA, req, "waking:");
- wake_up(&req->rq_wait_for_rep);
- }
- spin_unlock(&imp->imp_lock);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/module.h>
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_ha.h>
-#include <linux/lustre_net.h>
-#include <linux/init.h>
-#include <linux/lprocfs_status.h>
-
-
-
-extern int ptlrpc_init_portals(void);
-extern void ptlrpc_exit_portals(void);
-
-extern struct lprocfs_vars status_var_nm_1[];
-extern struct lprocfs_vars status_class_var[];
-
-int connmgr_setup(struct obd_device *obddev, obd_count len, void *buf)
-{
- struct recovd_obd *recovd = &obddev->u.recovd;
- int err;
- ENTRY;
-
- MOD_INC_USE_COUNT;
- memset(recovd, 0, sizeof(*recovd));
-
- err = recovd_setup(recovd);
- if (err) {
- MOD_DEC_USE_COUNT;
- RETURN(err);
- }
-
- RETURN(0);
-}
-
-int connmgr_cleanup(struct obd_device *dev)
-{
- struct recovd_obd *recovd = &dev->u.recovd;
- int err;
-
- err = recovd_cleanup(recovd);
- if (err)
- LBUG();
-
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-int connmgr_iocontrol(unsigned int cmd, struct lustre_handle *hdl, int len, void *karg,
- void *uarg)
-{
- struct ptlrpc_connection *conn = NULL;
- struct obd_device *obd = class_conn2obd(hdl);
- struct recovd_obd *recovd = &obd->u.recovd;
- struct obd_ioctl_data *data = karg;
- struct list_head *tmp;
- int rc = 0;
-
- ENTRY;
-
- if (cmd != OBD_IOC_RECOVD_NEWCONN && cmd != OBD_IOC_RECOVD_FAILCONN)
- RETURN(-EINVAL); /* XXX ENOSYS? */
-
- /* Find the connection that's been rebuilt or has failed. */
- spin_lock(&recovd->recovd_lock);
- list_for_each(tmp, &recovd->recovd_troubled_items) {
- conn = list_entry(tmp, struct ptlrpc_connection,
- c_recovd_data.rd_managed_chain);
-
- LASSERT(conn->c_recovd_data.rd_recovd == recovd); /* sanity */
-
- if (!strcmp(conn->c_remote_uuid, data->ioc_inlbuf1))
- break;
- conn = NULL;
- }
-
- if (!conn) {
- if (cmd == OBD_IOC_RECOVD_NEWCONN)
- GOTO(out, rc = -EINVAL);
- /* XXX macroize/inline and share with loop above */
- list_for_each(tmp, &recovd->recovd_managed_items) {
- conn = list_entry(tmp, struct ptlrpc_connection,
- c_recovd_data.rd_managed_chain);
-
- LASSERT(conn->c_recovd_data.rd_recovd == recovd);
-
- if (!strcmp(conn->c_remote_uuid, data->ioc_inlbuf1))
- break;
- conn = NULL;
- }
- if (!conn)
- GOTO(out, rc = -EINVAL);
- }
-
- if (cmd == OBD_IOC_RECOVD_FAILCONN) {
- spin_unlock(&recovd->recovd_lock);
- recovd_conn_fail(conn);
- spin_lock(&recovd->recovd_lock);
-
- /* Jump straight to the "failed" phase of recovery. */
- conn->c_recovd_data.rd_phase = RD_FAILED;
- goto out;
- }
-
-
- /* else (NEWCONN) */
- spin_lock(&conn->c_lock);
-
- /* whatever happens, reset the INVALID flag */
- conn->c_flags &= ~CONN_INVALID;
-
- /* XXX is this a good check? should we allow readdressing of
- * XXX conns that aren't in recovery?
- */
- if (conn->c_recovd_data.rd_phase != RD_PREPARING) {
- spin_unlock(&conn->c_lock);
- GOTO(out, rc = -EALREADY);
- }
-
- if (data->ioc_inllen2) {
- CERROR("conn %p UUID change %s -> %s\n",
- conn, conn->c_remote_uuid, data->ioc_inlbuf2);
- strcpy(conn->c_remote_uuid, data->ioc_inlbuf2);
- } else {
- CERROR("conn %p UUID %s reconnected\n", conn,
- conn->c_remote_uuid);
- }
- ptlrpc_readdress_connection(conn, conn->c_remote_uuid);
- spin_unlock(&conn->c_lock);
-
- conn->c_recovd_data.rd_phase = RD_PREPARED;
- wake_up(&recovd->recovd_waitq);
- out:
- spin_unlock(&recovd->recovd_lock);
- RETURN(rc);
-}
-
-static int connmgr_connect(struct lustre_handle *conn, struct obd_device *src,
- obd_uuid_t cluuid, struct recovd_obd *recovd,
- ptlrpc_recovery_cb_t recover)
-{
- return class_connect(conn, src, cluuid);
-}
-
-int connmgr_attach(struct obd_device *dev, obd_count len, void *data)
-{
- return lprocfs_reg_obd(dev, status_var_nm_1, dev);
-}
-
-int conmgr_detach(struct obd_device *dev)
-{
- return lprocfs_dereg_obd(dev);
-}
-/* use obd ops to offer management infrastructure */
-static struct obd_ops recovd_obd_ops = {
- o_attach: connmgr_attach,
- o_detach: conmgr_detach,
- o_setup: connmgr_setup,
- o_cleanup: connmgr_cleanup,
- o_iocontrol: connmgr_iocontrol,
- o_connect: connmgr_connect,
- o_disconnect: class_disconnect
-};
-
-static int __init ptlrpc_init(void)
-{
- int rc;
- rc = ptlrpc_init_portals();
- if (rc)
- RETURN(rc);
- ptlrpc_init_connection();
- rc = class_register_type(&recovd_obd_ops, status_class_var,
- LUSTRE_HA_NAME);
- if (rc)
- RETURN(rc);
- ptlrpc_put_connection_superhack = ptlrpc_put_connection;
- return 0;
-}
-
-static void __exit ptlrpc_exit(void)
-{
- class_unregister_type(LUSTRE_HA_NAME);
- ptlrpc_exit_portals();
- ptlrpc_cleanup_connection();
-}
-
-/* recovd.c */
-EXPORT_SYMBOL(ptlrpc_recovd);
-EXPORT_SYMBOL(recovd_conn_fail);
-EXPORT_SYMBOL(recovd_conn_manage);
-EXPORT_SYMBOL(recovd_conn_fixed);
-EXPORT_SYMBOL(recovd_setup);
-EXPORT_SYMBOL(recovd_cleanup);
-
-/* connection.c */
-EXPORT_SYMBOL(ptlrpc_readdress_connection);
-EXPORT_SYMBOL(ptlrpc_get_connection);
-EXPORT_SYMBOL(ptlrpc_put_connection);
-EXPORT_SYMBOL(ptlrpc_connection_addref);
-EXPORT_SYMBOL(ptlrpc_init_connection);
-EXPORT_SYMBOL(ptlrpc_cleanup_connection);
-
-/* niobuf.c */
-EXPORT_SYMBOL(ptlrpc_send_bulk);
-EXPORT_SYMBOL(ptlrpc_register_bulk);
-EXPORT_SYMBOL(ptlrpc_abort_bulk);
-EXPORT_SYMBOL(ptlrpc_reply);
-EXPORT_SYMBOL(ptlrpc_error);
-EXPORT_SYMBOL(ptlrpc_resend_req);
-EXPORT_SYMBOL(ptl_send_rpc);
-EXPORT_SYMBOL(ptlrpc_link_svc_me);
-EXPORT_SYMBOL(obd_brw_set_free);
-EXPORT_SYMBOL(obd_brw_set_new);
-EXPORT_SYMBOL(obd_brw_set_add);
-
-/* client.c */
-EXPORT_SYMBOL(ptlrpc_init_client);
-EXPORT_SYMBOL(ptlrpc_cleanup_client);
-EXPORT_SYMBOL(ptlrpc_req_to_uuid);
-EXPORT_SYMBOL(ptlrpc_uuid_to_connection);
-EXPORT_SYMBOL(ptlrpc_queue_wait);
-EXPORT_SYMBOL(ptlrpc_continue_req);
-EXPORT_SYMBOL(ptlrpc_replay_req);
-EXPORT_SYMBOL(ptlrpc_restart_req);
-EXPORT_SYMBOL(ptlrpc_prep_req);
-EXPORT_SYMBOL(ptlrpc_free_req);
-EXPORT_SYMBOL(ptlrpc_req_finished);
-EXPORT_SYMBOL(ptlrpc_prep_bulk);
-EXPORT_SYMBOL(ptlrpc_free_bulk);
-EXPORT_SYMBOL(ptlrpc_prep_bulk_page);
-EXPORT_SYMBOL(ptlrpc_free_bulk_page);
-EXPORT_SYMBOL(ll_brw_sync_wait);
-
-/* service.c */
-EXPORT_SYMBOL(ptlrpc_init_svc);
-EXPORT_SYMBOL(ptlrpc_stop_all_threads);
-EXPORT_SYMBOL(ptlrpc_start_thread);
-EXPORT_SYMBOL(ptlrpc_unregister_service);
-
-/* pack_generic.c */
-EXPORT_SYMBOL(lustre_pack_msg);
-EXPORT_SYMBOL(lustre_msg_size);
-EXPORT_SYMBOL(lustre_unpack_msg);
-EXPORT_SYMBOL(lustre_msg_buf);
-
-/* recover.c */
-EXPORT_SYMBOL(ptlrpc_run_recovery_upcall);
-EXPORT_SYMBOL(ptlrpc_reconnect_import);
-EXPORT_SYMBOL(ptlrpc_replay);
-EXPORT_SYMBOL(ptlrpc_resend);
-EXPORT_SYMBOL(ptlrpc_wake_delayed);
-
-MODULE_AUTHOR("Cluster File Systems, Inc <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Request Processor v1.0");
-MODULE_LICENSE("GPL");
-
-module_init(ptlrpc_init);
-module_exit(ptlrpc_exit);
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#define DEBUG_SUBSYSTEM S_RPC
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_net.h>
-
-extern int request_in_callback(ptl_event_t *ev);
-
-static int ptlrpc_check_event(struct ptlrpc_service *svc,
- struct ptlrpc_thread *thread, ptl_event_t *event)
-{
- int rc;
- ENTRY;
-
- spin_lock(&svc->srv_lock);
-
- if (thread->t_flags & SVC_STOPPING)
- GOTO(out, rc = 1);
-
- LASSERT ((thread->t_flags & SVC_EVENT) == 0);
- LASSERT (ptl_is_valid_handle (&svc->srv_eq_h));
-
- rc = PtlEQGet(svc->srv_eq_h, event);
- switch (rc)
- {
- case PTL_OK:
- thread->t_flags |= SVC_EVENT;
- GOTO(out, rc = 1);
-
- case PTL_EQ_EMPTY:
- GOTO(out, rc = 0);
-
- default:
- CERROR("BUG: PtlEQGet returned %d\n", rc);
- LBUG();
- }
- out:
- spin_unlock(&svc->srv_lock);
- return rc;
-}
-
-struct ptlrpc_service *
-ptlrpc_init_svc(__u32 nevents, __u32 nbufs,
- __u32 bufsize, __u32 max_req_size,
- int req_portal, int rep_portal,
- obd_uuid_t uuid, svc_handler_t handler, char *name)
-{
- int err;
- int rc, i;
- struct ptlrpc_service *service;
- ENTRY;
-
- OBD_ALLOC(service, sizeof(*service));
- if (!service)
- RETURN(NULL);
-
- service->srv_name = name;
- spin_lock_init(&service->srv_lock);
- INIT_LIST_HEAD(&service->srv_threads);
- init_waitqueue_head(&service->srv_waitq);
-
- service->srv_max_req_size = max_req_size;
- service->srv_buf_size = bufsize;
- INIT_LIST_HEAD(&service->srv_rqbds);
- service->srv_nrqbds = 0;
- atomic_set(&service->srv_nrqbds_receiving, 0);
-
- service->srv_rep_portal = rep_portal;
- service->srv_req_portal = req_portal;
- service->srv_handler = handler;
-
- err = kportal_uuid_to_peer(uuid, &service->srv_self);
- if (err) {
- CERROR("%s: cannot get peer for uuid '%s'\n", name, uuid);
- OBD_FREE(service, sizeof(*service));
- RETURN(NULL);
- }
-
- rc = PtlEQAlloc(service->srv_self.peer_ni, nevents,
- request_in_callback, &(service->srv_eq_h));
-
- if (rc != PTL_OK) {
- CERROR("%s: PtlEQAlloc failed: %d\n", name, rc);
- OBD_FREE(service, sizeof(*service));
- RETURN(NULL);
- }
-
- for (i = 0; i < nbufs; i++) {
- struct ptlrpc_request_buffer_desc *rqbd;
-
- OBD_ALLOC(rqbd, sizeof(*rqbd));
- if (rqbd == NULL)
- GOTO(failed, NULL);
-
- rqbd->rqbd_service = service;
- ptl_set_inv_handle(&rqbd->rqbd_me_h);
- atomic_set(&rqbd->rqbd_refcount, 0);
- OBD_ALLOC(rqbd->rqbd_buffer, service->srv_buf_size);
- if (rqbd->rqbd_buffer == NULL) {
- OBD_FREE(rqbd, sizeof(*rqbd));
- GOTO(failed, NULL);
- }
- list_add(&rqbd->rqbd_list, &service->srv_rqbds);
- service->srv_nrqbds++;
-
- ptlrpc_link_svc_me(rqbd);
- }
-
- CDEBUG(D_NET, "Starting service listening on portal %d (eq: %p)\n",
- service->srv_req_portal, service->srv_eq_h.handle_idx);
-
- RETURN(service);
-failed:
- ptlrpc_unregister_service(service);
- return NULL;
-}
-
-static int handle_incoming_request(struct obd_device *obddev,
- struct ptlrpc_service *svc,
- ptl_event_t *event,
- struct ptlrpc_request *request)
-{
- struct ptlrpc_request_buffer_desc *rqbd = event->mem_desc.user_ptr;
- int rc;
-
- /* FIXME: If we move to an event-driven model, we should put the request
- * on the stack of mds_handle instead. */
-
- LASSERT (atomic_read (&rqbd->rqbd_refcount) > 0);
- LASSERT ((event->mem_desc.options & PTL_MD_IOV) == 0);
- LASSERT (rqbd->rqbd_service == svc);
- LASSERT (rqbd->rqbd_buffer == event->mem_desc.start);
- LASSERT (event->offset + event->mlength <= svc->srv_buf_size);
-
- memset(request, 0, sizeof(*request));
- request->rq_svc = svc;
- request->rq_obd = obddev;
- request->rq_xid = event->match_bits;
- request->rq_reqmsg = event->mem_desc.start + event->offset;
- request->rq_reqlen = event->mlength;
-
- rc = -EINVAL;
-
- if (request->rq_reqlen < sizeof(struct lustre_msg)) {
- CERROR("incomplete request (%d): ptl %d from "LPX64" xid "
- LPD64"\n",
- request->rq_reqlen, svc->srv_req_portal,
- event->initiator.nid, request->rq_xid);
- goto out;
- }
-
- CDEBUG(D_RPCTRACE, "Handling RPC pid:xid:nid:opc %d:"
- LPX64":%x:%d\n",
- NTOH__u32(request->rq_reqmsg->status),
- request->rq_xid,
- event->initiator.nid,
- NTOH__u32(request->rq_reqmsg->opc));
-
- if (NTOH__u32(request->rq_reqmsg->type) != PTL_RPC_MSG_REQUEST) {
- CERROR("wrong packet type received (type=%u)\n",
- request->rq_reqmsg->type);
- goto out;
- }
-
- if (request->rq_reqmsg->magic != PTLRPC_MSG_MAGIC) {
- CERROR("wrong lustre_msg magic %d: ptl %d from "LPX64" xid "
- LPD64"\n",
- request->rq_reqmsg->magic, svc->srv_req_portal,
- event->initiator.nid, request->rq_xid);
- goto out;
- }
-
- if (request->rq_reqmsg->version != PTLRPC_MSG_VERSION) {
- CERROR("wrong lustre_msg version %d: ptl %d from "LPX64" xid "
- LPD64"\n",
- request->rq_reqmsg->version, svc->srv_req_portal,
- event->initiator.nid, request->rq_xid);
- goto out;
- }
-
- CDEBUG(D_NET, "got req "LPD64" (md: %p + %d)\n", request->rq_xid,
- event->mem_desc.start, event->offset);
-
- request->rq_peer.peer_nid = event->initiator.nid;
- /* FIXME: this NI should be the incoming NI.
- * We don't know how to find that from here. */
- request->rq_peer.peer_ni = svc->srv_self.peer_ni;
-
- request->rq_export = class_conn2export((struct lustre_handle *)
- request->rq_reqmsg);
-
- if (request->rq_export) {
- request->rq_connection = request->rq_export->exp_connection;
- ptlrpc_connection_addref(request->rq_connection);
- } else {
- /* create a (hopefully temporary) connection that will be used
- * to send the reply if this call doesn't create an export.
- * XXX revisit this when we revamp ptlrpc */
- request->rq_connection =
- ptlrpc_get_connection(&request->rq_peer, NULL);
- }
-
- rc = svc->srv_handler(request);
- ptlrpc_put_connection(request->rq_connection);
-
- out:
- if (atomic_dec_and_test (&rqbd->rqbd_refcount)) /* last reference? */
- ptlrpc_link_svc_me (rqbd);
-
- return rc;
-}
-
-/* Don't use daemonize, it removes fs struct from new thread (bug 418) */
-static void ptlrpc_daemonize(void)
-{
- exit_mm(current);
-
- current->session = 1;
- current->pgrp = 1;
- current->tty = NULL;
-
- exit_files(current);
-}
-
-static int ptlrpc_main(void *arg)
-{
- struct ptlrpc_svc_data *data = (struct ptlrpc_svc_data *)arg;
- struct obd_device *obddev = data->dev;
- struct ptlrpc_service *svc = data->svc;
- struct ptlrpc_thread *thread = data->thread;
- struct ptlrpc_request *request;
- ptl_event_t *event;
- int rc = 0;
-
- ENTRY;
-
- lock_kernel();
- ptlrpc_daemonize();
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- sigfillset(¤t->blocked);
- recalc_sigpending();
-#else
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
-#endif
-
-#ifdef __arch_um__
- sprintf(current->comm, "%s|%d", data->name,current->thread.extern_pid);
-#else
- strcpy(current->comm, data->name);
-#endif
- unlock_kernel();
-
- OBD_ALLOC(event, sizeof(*event));
- if (!event)
- GOTO(out, rc = -ENOMEM);
- OBD_ALLOC(request, sizeof(*request));
- if (!request)
- GOTO(out_event, rc = -ENOMEM);
-
- /* Record that the thread is running */
- thread->t_flags = SVC_RUNNING;
- wake_up(&thread->t_ctl_waitq);
-
- /* XXX maintain a list of all managed devices: insert here */
-
- /* And now, loop forever on requests */
- while (1) {
- wait_event(svc->srv_waitq,
- ptlrpc_check_event(svc, thread, event));
-
- if (thread->t_flags & SVC_STOPPING) {
- spin_lock(&svc->srv_lock);
- thread->t_flags &= ~SVC_STOPPING;
- spin_unlock(&svc->srv_lock);
-
- EXIT;
- break;
- }
-
- if (thread->t_flags & SVC_EVENT) {
- spin_lock(&svc->srv_lock);
- thread->t_flags &= ~SVC_EVENT;
- spin_unlock(&svc->srv_lock);
-
- rc = handle_incoming_request(obddev, svc, event,
- request);
- continue;
- }
-
- CERROR("unknown break in service");
- LBUG();
- EXIT;
- break;
- }
-
- OBD_FREE(request, sizeof(*request));
-out_event:
- OBD_FREE(event, sizeof(*event));
-out:
- thread->t_flags = SVC_STOPPED;
- wake_up(&thread->t_ctl_waitq);
-
- CDEBUG(D_NET, "service thread exiting, process %d: rc = %d\n",
- current->pid, rc);
- return rc;
-}
-
-static void ptlrpc_stop_thread(struct ptlrpc_service *svc,
- struct ptlrpc_thread *thread)
-{
- spin_lock(&svc->srv_lock);
- thread->t_flags = SVC_STOPPING;
- spin_unlock(&svc->srv_lock);
-
- wake_up(&svc->srv_waitq);
- wait_event(thread->t_ctl_waitq, (thread->t_flags & SVC_STOPPED));
-}
-
-void ptlrpc_stop_all_threads(struct ptlrpc_service *svc)
-{
- spin_lock(&svc->srv_lock);
- while (!list_empty(&svc->srv_threads)) {
- struct ptlrpc_thread *thread;
- thread = list_entry(svc->srv_threads.next, struct ptlrpc_thread,
- t_link);
- spin_unlock(&svc->srv_lock);
- ptlrpc_stop_thread(svc, thread);
- spin_lock(&svc->srv_lock);
- list_del(&thread->t_link);
- OBD_FREE(thread, sizeof(*thread));
- }
- spin_unlock(&svc->srv_lock);
-}
-
-int ptlrpc_start_thread(struct obd_device *dev, struct ptlrpc_service *svc,
- char *name)
-{
- struct ptlrpc_svc_data d;
- struct ptlrpc_thread *thread;
- int rc;
- ENTRY;
-
- OBD_ALLOC(thread, sizeof(*thread));
- if (thread == NULL) {
- LBUG();
- RETURN(-ENOMEM);
- }
- init_waitqueue_head(&thread->t_ctl_waitq);
-
- d.dev = dev;
- d.svc = svc;
- d.name = name;
- d.thread = thread;
-
- spin_lock(&svc->srv_lock);
- list_add(&thread->t_link, &svc->srv_threads);
- spin_unlock(&svc->srv_lock);
-
- rc = kernel_thread(ptlrpc_main, (void *) &d, CLONE_VM | CLONE_FILES);
- if (rc < 0) {
- CERROR("cannot start thread\n");
- OBD_FREE(thread, sizeof(*thread));
- RETURN(rc);
- }
- wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_RUNNING);
-
- RETURN(0);
-}
-
-int ptlrpc_unregister_service(struct ptlrpc_service *service)
-{
- int rc;
-
- LASSERT (list_empty (&service->srv_threads));
-
- /* XXX We could reply (with failure) to all buffered requests
- * _after_ unlinking _all_ the request buffers, but _before_
- * freeing them.
- */
-
- while (!list_empty (&service->srv_rqbds)) {
- struct ptlrpc_request_buffer_desc *rqbd =
- list_entry (service->srv_rqbds.next,
- struct ptlrpc_request_buffer_desc,
- rqbd_list);
-
- list_del (&rqbd->rqbd_list);
-
- LASSERT (atomic_read (&rqbd->rqbd_refcount) > 0);
- /* refcount could be anything; it's possible for the
- * buffers to continued to get filled after all the server
- * threads exited. But we know they _have_ exited.
- */
-
- (void) PtlMEUnlink(rqbd->rqbd_me_h);
- /* The callback handler could have unlinked this ME already
- * (we're racing with her) but it's safe to ensure it _has_
- * been unlinked.
- */
-
- OBD_FREE (rqbd->rqbd_buffer, service->srv_buf_size);
- OBD_FREE (rqbd, sizeof (*rqbd));
- service->srv_nrqbds--;
- }
-
- LASSERT (service->srv_nrqbds == 0);
-
- rc = PtlEQFree(service->srv_eq_h);
- if (rc)
- CERROR("PtlEQFree failed: %d\n", rc);
-
- OBD_FREE(service, sizeof(*service));
- if (rc)
- LBUG();
- return rc;
-}
+++ /dev/null
-.Xrefs
-lustre.spec
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
+++ /dev/null
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-EXTRA_DIST = license-status maketags.sh lustre.spec version_tag.pl $(initd_SCRIPTS)
-initddir = $(sysconfdir)/init.d
-initd_SCRIPTS = lustre
-include $(top_srcdir)/Rules
-
+++ /dev/null
-#!/bin/sh
-
-for f in `cat $1` ; do
- diff -u $2-pristine/$f $2/$f
-done
+++ /dev/null
-#! /bin/sh
-# license-status - Display the status of files in the current directory
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-#
-# Gordon Matzigkeit <gord@fig.org>, 2001-09-27
-
-for f in `find . -type f | sort`; do
- case "$f" in
- *~ | *.orig | *.gz | */config.* | *.o | \
- */CVS/* | */.cvsignore | */.depfiles/* | \
- */COPYING | */ChangeLog)
- continue
- ;;
- esac
-
- if head -20 "$f" | egrep -e 'GNU' > /dev/null; then
- echo "gpled $f"
- elif head -20 "$f" | egrep -e '\([Cc]\)' > /dev/null; then
- echo "copyrighted $f"
- else
- echo "bare $f"
- fi
-done | sort
+++ /dev/null
-#!/bin/sh
-#
-# lustre This shell script takes care of starting and stopping Lustre
-#
-# chkconfig: 345 99 1
-# description: Lustre Lite network File System. \
-# This starts both Lustre client and server functions.
-# processname: lconf
-# config: /etc/lustre/config.xml
-# pidfile: /var/run/lustre.pid
-
-SERVICE=lustre
-LOCK=/var/lock/subsys/$SERVICE
-
-: ${LUSTRE_CFG:=/etc/lustre/lustre.cfg}
-[ -f ${LUSTRE_CFG} ] && . ${LUSTRE_CFG}
-
-: ${LUSTRE_CONFIG_XML:=/etc/lustre/config.xml}
-: ${LCONF:=/usr/sbin/lconf}
-: ${LCONF_START_ARGS:="${LUSTRE_CONFIG_XML}"}
-: ${LCONF_STOP_ARGS:="--force --cleanup ${LUSTRE_CONFIG_XML}"}
-
-# Source function library.
-if [ -f /etc/init.d/functions ] ; then
- . /etc/init.d/functions
-fi
-
-# Source networking configuration.
-if [ -f /etc/sysconfig/network ] ; then
- . /etc/sysconfig/network
-fi
-
-# Check that networking is up.
-[ "${NETWORKING}" = "no" ] && exit 0
-
-[ -x ${LCONF} -a -f ${LUSTRE_CONFIG_XML} ] || exit 0
-
-start() {
- echo -n "Starting $SERVICE: "
- ${LCONF} ${LCONF_START_ARGS}
- RETVAL=$?
- echo $SERVICE
- [ $RETVAL -eq 0 ] && touch $LOCK
-}
-
-stop() {
- echo -n "Shutting down $SERVICE: "
- ${LCONF} ${LCONF_STOP_ARGS}
- echo $SERVICE
- rm -f $LOCK
-}
-
-restart() {
- stop
- start
-}
-
-# See how we were called.
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart)
- restart
- ;;
- status)
- status $SERVICE
- ;;
- *)
- echo "Usage: $SERVICE {start|stop|restart|status}"
- exit 1
-esac
-
-exit $RETVAL
+++ /dev/null
-# lustre.spec
-%define version HEAD
-%define kversion @RELEASE@
-%define linuxdir @LINUX@
-%define portalsdir @PORTALS@
-%define portalslibdir @PORTALSLIB@
-Release: 0208282230chaos
-
-Summary: Lustre Lite File System
-Name: lustre-lite
-Version: %{version}
-Copyright: GPL
-Group: Utilities/System
-Requires: lustre-modules, PyXML
-BuildRoot: /var/tmp/lustre-%{version}-root
-Source: ftp://ftp.lustre.com/pub/lustre/lustre-%{version}.tar.gz
-
-%description
-The Lustre Lite Cluster File System: kernel drivers for file system,
-servers and utilities.
-
-%package -n lustre-modules
-Summary: Kernel Lustre drivers for Linux %{kversion}
-Requires: portals-modules
-Group: Development/Kernel
-
-%description -n lustre-modules
-Lustre file System, server and network drivers for Linux %{kversion}.
-
-%package -n lustre-source
-Summary: Object-Based Disk storage driver source
-Group: Development/Kernel
-
-%description -n lustre-source
-Lustre Lite Source for further development
-
-%package -n lustre-doc
-Summary: Documentation and sample configuration files
-Group: Documentation
-# FIXME: BuildArch overrides all the packages in rpm 4.0.4-7x
-#BuildArch: noarch
-
-%description -n lustre-doc
-Documentation and sample configuration files for Lustre
-
-%prep
-%setup -qn lustre-%{version}
-
-%build
-rm -rf $RPM_BUILD_ROOT
-
-# Set an explicit path to our Linux tree, if we can.
-./configure --with-linux='%{linuxdir}' --with-portals='%{portalsdir}' --with-portalslib='%{portalslibdir}'
-make
-
-%install
-make install prefix=$RPM_BUILD_ROOT
-
-# Create the pristine source directory.
-mkdir -p $RPM_BUILD_ROOT/usr/src
-rm -f lustre-source
-ln -s $RPM_BUILD_ROOT/usr/src lustre-source
-make distdir distdir=lustre-source/lustre-%{version}
-
-%files
-%attr(-, root, root) /usr/sbin/lmc
-%attr(-, root, root) /usr/sbin/lctl
-%attr(-, root, root) /usr/sbin/lconf
-%attr(-, root, root) /usr/lib/lustre/examples/llmount.sh
-%attr(-, root, root) /usr/lib/lustre/examples/llmountcleanup.sh
-%attr(-, root, root) /usr/lib/lustre/examples/llecho.sh
-%attr(-, root, root) /usr/lib/lustre/examples/local.sh
-%attr(-, root, root) /usr/lib/lustre/examples/uml.sh
-%attr(-, root, root) /usr/lib/lustre/examples/lov.sh
-%attr(-, root, root) /etc/init.d/lustre
-
-%files -n lustre-doc
-%attr(-, root, root) %doc COPYING FDL
-%attr(-, root, root) %doc doc/lustre.pdf doc/lustre-HOWTO.txt
-%attr(-, root, root) %doc tests/client-echo.cfg tests/client-mount.cfg
-%attr(-, root, root) %doc tests/client-mount2.cfg
-%attr(-, root, root) %doc tests/elan-client.cfg tests/elan-server.cfg
-%attr(-, root, root) %doc tests/ldlm.cfg tests/lustre.cfg
-%attr(-, root, root) %doc tests/mds.cfg tests/net-client.cfg
-%attr(-, root, root) %doc tests/net-local.cfg tests/net-server.cfg
-%attr(-, root, root) %doc tests/obdecho.cfg tests/obdfilter.cfg
-
-%files -n lustre-modules
-%attr(-, root, root) %doc COPYING
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/extN.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/ldlm.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/llite.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/mdc.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/mds.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/mds_extN.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/obdclass.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/obdecho.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/obdfilter.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/lov.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/osc.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/ost.o
-%attr(-, root, root) /lib/modules/%{kversion}/kernel/fs/lustre/ptlrpc.o
-
-%files -n lustre-source
-%attr(-, root, root) /usr/src/lustre-%{version}
-
-%post
-if [ ! -e /dev/obd ]; then
- mknod /dev/obd c 10 241
-fi
-depmod -ae || exit 0
-
-grep -q obdclass /etc/modules.conf || \
- echo 'alias char-major-10-241 obdclass' >> /etc/modules.conf
-
-grep -q '/dev/obd' /etc/modules.conf || \
- echo 'alias /dev/obd obdclass' >> /etc/modules.conf
-
-grep -q '/dev/lustre' /etc/modules.conf || \
- echo 'alias /dev/lustre obdclass' >> /etc/modules.conf
-
-%postun
-depmod -ae || exit 0
-
-%clean
-#rm -rf $RPM_BUILD_ROOT
-
-# end of file
+++ /dev/null
-#! /bin/sh
-# nodelustre - Start and stop Lustre on MCR nodes
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Gord Eagle <gord@clusterfs.com>, 2002-09-10
-
-# Set this to the shared config file.
-MASTER_CONFIG=http://emcri/lustre.xml
-CONFIG=/etc/lustre/lustre.xml
-COMPUTE_NODE=client
-
-LCONF=/usr/local/cfs/lustre/utils/lconf
-WGET=wget
-
-case "$1" in
-start | stop)
- # Fetch the config file. We can't use --output-document because it
- # makes Wget ignore timestamping.
- if test -n "$MASTER_CONFIG"; then
- (cd `echo "$CONFIG" | sed 's%/[^/]*$%%'` && \
- $WGET --timestamping "$MASTER_CONFIG") || exit $?
- fi
-
- # Map all client nodes to the COMPUTE_NODE virtual node.
- if test -n "$COMPUTE_NODE" && nodeattr compute; then
- node=" --node $COMPUTE_NODE"
- else
- node=
- fi
-
- # If we're stopping, do the lconf cleanup.
- if test "$1" = stop; then
- cleanup=' --cleanup'
- else
- cleanup=
- fi
-
- $LCONF$cleanup$node "$CONFIG"
- ;;
-
-*)
- echo "$0 {start|stop}" 1>&2
- exit 1
- ;;
-esac
-
-exit 0
+++ /dev/null
-#!/usr/bin/perl
-# -*- Mode: perl; indent-tabs-mode: nil; cperl-indent-level: 4 -*-
-
-use strict;
-use diagnostics;
-use IO::File;
-use Time::Local;
-
-my $pristine = 1;
-my $kernver;
-
-sub get_tag()
-{
- my $tag;
-
- my $tagfile = new IO::File;
- if (!$tagfile->open("CVS/Tag")) {
- return "HEAD";
- } else {
- my $tmp = <$tagfile>;
- $tagfile->close();
-
- $tmp =~ m/T(.*)/;
- return $1;
- }
-}
-
-sub get_latest_mtime()
-{
- my %months=("Jan" => 0, "Feb" => 1, "Mar" => 2, "Apr" => 3, "May" => 4,
- "Jun" => 5, "Jul" => 6, "Aug" => 7, "Sep" => 8, "Oct" => 9,
- "Nov" => 10, "Dec" => 11);
-
- my $last_mtime = 0;
- my @entries = `find . -name Entries`;
- my $entry_file;
- foreach $entry_file (@entries) {
- chomp($entry_file);
- my $entry = new IO::File;
- if (!$entry->open($entry_file)) {
- die "unable to open $entry_file: $!\n";
- }
- my $line;
- while (defined($line = <$entry>)) {
- chomp($line);
- #print "line: $line\n";
- my ($junk, $file, $version, $date) = split(/\//, $line);
-
- #print "junk: $junk\nfile: $file\nver: $version\ndate: $date\n";
- #print "last_mtime: " . localtime($last_mtime) . "\n";
-
- if ($junk eq "D" ||
- $file eq "lustre.spec.in" ||
- $file !~ m/\.(c|h|am|in)$/) {
- next;
- }
-
- my $cur_dir = $entry_file;
- $cur_dir =~ s/\/CVS\/Entries$//;
- my @statbuf = stat("$cur_dir/$file");
- my $mtime = $statbuf[9];
- my $local_date = gmtime($mtime);
- if ($local_date ne $date &&
- $file ne "lustre.spec.in") {
- #print "$file : " . localtime($mtime) . "\n";
- $pristine = 0;
- }
-
- if ($mtime > $last_mtime) {
- $last_mtime = $mtime;
- }
-
- if ($date) {
- my @t = split(/ +/, $date);
- if (int(@t) != 5) {
- #print "skipping: $date\n";
- next;
- }
- my ($hours, $min, $sec) = split(/:/, $t[3]);
- my ($mon, $mday, $year) = ($t[1], $t[2], $t[4]);
- my $secs = 0;
- $mon = $months{$mon};
- $secs = timelocal($sec, $min, $hours, $mday, $mon, $year);
- if ($secs > $last_mtime) {
- $last_mtime = $secs;
- }
- }
- }
- $entry->close();
- }
- return $last_mtime;
-}
-
-sub get_linuxdir()
-{
- my $config = new IO::File;
- my ($line, $dir);
- if (!$config->open("Makefile")) {
- die "Run ./configure first\n";
- }
- while (defined($line = <$config>)) {
- chomp($line);
- if ($line =~ /LINUX = (.*)/) {
- $dir = $1;
- last;
- }
- }
- $config->close();
- my $ver = new IO::File;
- if (!$ver->open("$dir/include/linux/version.h")) {
- die "Run make dep on $dir\n";
- }
- while(defined($line = <$ver>)) {
- $line =~ /\#define UTS_RELEASE "(.*)"/;
- if ($1) {
- $kernver = $1;
- last;
- }
- }
- $ver->close();
- chomp($kernver);
- $dir =~ s/\//\./g;
- return $dir;
-}
-
-sub generate_ver($$$)
-{
- my $tag = shift;
- my $mtime = shift;
- my $linuxdir = shift;
-
- #print "localtime: " . localtime($mtime) . "\n";
-
- my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
- localtime($mtime);
- $year += 1900;
- $mon++;
- my $show_last = sprintf("%04d%02d%02d%02d%02d%02d", $year, $mon, $mday,
- $hour, $min, $sec);
-
- print "#define BUILD_VERSION \"";
- if ($pristine) {
- print "$tag-$show_last-PRISTINE-$linuxdir-$kernver\"\n";
- } else {
- print "$tag-$show_last-CHANGED-$linuxdir-$kernver\"\n";
- }
-}
-
-if ($ARGV[0]) {
- chdir($ARGV[0]);
-}
-my $linuxdir = get_linuxdir();
-my $tag = get_tag();
-my $mtime = get_latest_mtime();
-generate_ver($tag, $mtime, $linuxdir);
-
-exit(0);
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
-openunlink
-testreq
-truncate
-directio
-openme
-writeme
-mcreate
-munlink
-tchmod
-toexcl
-fsx
-test_brw
-newfile
-openclose
-createdestroy
-createmany
-mkdirmany
-lovstripe
-*.xml
-stat
-setuid
+++ /dev/null
-# Lustre test Makefile
-DEFS=
-CPPFLAGS = -I. -I$(PORTALS)/include -I$(top_srcdir)/include -D_LARGEFILE64_SOURCE
-CFLAGS := -g -Wall
-# LDADD = -lldap
-# LDADD := -lreadline -ltermcap # -lefence
-EXTRA_DIST = $(pkgexample_SCRIPTS) $(noinst_SCRIPTS) $(noinst_DATA) \
- common.sh lustre.cfg \
- client-echo.cfg elan-server.cfg net-client.cfg obdecho.cfg \
- client-mount.cfg ldlm.cfg net-local.cfg obdfilter.cfg \
- client-mount2.cfg lustre.cfg net-server.cfg sanity.sh \
- rundbench \
- elan-client.cfg mds.cfg trivial.sh
-pkgexampledir = '${exec_prefix}/usr/lib/$(PACKAGE)/examples'
-pkgexample_SCRIPTS = llmount.sh llmountcleanup.sh llecho.sh local.sh uml.sh lov.sh
-noinst_SCRIPTS = llsetup.sh llrsetup.sh llcleanup.sh
-noinst_DATA = lustre.cfg
-noinst_SCRIPTS += fs.sh intent-test.sh intent-test2.sh leak_finder.pl \
- lldlm.sh llecho.sh llext3.sh llmodules.sh llmount-client.sh \
- llmount-server.sh llmount.sh llmountcleanup.sh llrext3.sh \
- llrmount.sh llsimple.sh mdcreq.sh mdcreqcleanup.sh \
- ostreq.sh runfailure-client-mds-recover.sh runfailure-mds \
- runfailure-net runfailure-ost runiozone runregression-net.sh \
- runtests runvmstat snaprun.sh tbox.sh common.sh
-noinst_PROGRAMS = openunlink testreq truncate directio openme writeme mcreate
-noinst_PROGRAMS += munlink tchmod toexcl fsx test_brw openclose createdestroy
-noinst_PROGRAMS += lovstripe stat createmany mkdirmany setuid # ldaptest
-
-# ldaptest_SOURCES = ldaptest.c
-tchmod_SOURCES = tchmod.c
-toexcl_SOURCES = toexcl.c
-testreq_SOURCES = testreq.c
-mcreate_SOURCES = mcreate.c
-munlink_SOURCES = munlink.c
-truncate_SOURCES = truncate.c
-directio_SOURCES = directio.c
-openunlink_SOURCES = openunlink.c
-openme_SOURCES = openme.c
-writeme_SOURCES = writeme.c
-fsx_SOURCES = fsx.c
-test_brw_SOURCES = test_brw.c
-openclose_SOURCES = openclose.c
-createdestroy_SOURCES = createdestroy.c
-lovstripe_SOURCES = lovstripe.c
-stat_SOURCES = stat.c
-createmany_SOURCES = createmany.c
-mkdirmany_SOURCES = mkdirmany.c
-setuid_SOURCES = setuid.c
-
-include $(top_srcdir)/Rules
+++ /dev/null
-1. How to build .xml configs:
-The various .xml configs in the tests/ directory are built by running the
-corresponding .sh script. The .sh script runs a series of lmc (Lustre make
-config) commands in order to build up an XML file. It is much easier to
-simply edit a .sh script and rebuild your XML config file than trying to
-edit the XML directly.
-
-For a loopback setup with a mounted filesystem, you could do something like:
-
- sh local.sh
- ../utils/lconf --reformat local.xml
-
-This will configure an MDS, an OBD/OST, and a filesystem client all running
-on the same system and communicating over the TCP loopback interface. If
-the --reformat option is given, then the OST and MDS devices will be
-formatted. This is required the first time you set up the system, or if
-you think you have corrupted the filesystems after you hit a bug.
-
-A more complex configuration, using a separate host for each of the MDS,
-OBD/OST, and filesystem client functions is in uml.sh. It configures 3
-systems, and the OST system (uml2) serves up multiple OST devices, and
-the client accesses these via a logical object volume (LOV) driver (which
-essentially stripes both of the OST devices into a single storage device.
-
-This configuration could be run on any 3 systems with the following commands:
-
- sh uml.sh
- system1# ../utils/lconf --reformat --node uml1 uml.xml
- system2# ../utils/lconf --reformat --node uml2 uml.xml
- system3# ../utils/lconf --node uml3 uml.xml
-
-The "--node <name>" parameter tells lconf to use the configuration for
-the node "name" in the XML configuration file. If the hostnames were
-already "uml1", "uml2", and "uml3", then the "--node" parameter would
-not need to be given. The internals of lconf and portals handle the
-configuration details for setting up netowrking.
-
-2. runregression-net.sh and runregression-brw.sh
-
-This test performs raw block and attribute requests against a real or
-"null" OST device. It is useful for generating isolated load on the
-OST device, while avoiding the need to run tests through the filesystem.
-This can be useful for testing the network part of Lustre in isolation,
-or doing RPC and bulk I/O performance tests against an OST.
-
-If things are alright it goes through a series of tests single threaded,
-multithreaded, using getattr and brw (both read and write, with single
-page and vector I/O, doing basic data checking of each page).
-
-You can create a simple echo client by running the "llecho.sh" to
-run the tests locally (over TCP loopback), or edit llecho.sh to
-specify the SERVER and CLIENT names. You would then set up as normal:
-
- # if you are using a remote server, first run:
- server# ../utils/lconf echo.xml
-
-Configure the client (or if you are running a single system only):
-
- client# ../utils/lconf echo.xml
- client# sh runregression-net.sh
-
-3. runtests
-
-The runtests script does a series of simple file-based tests using a
-filesystem. You need to have an XML file as appropriate for your setup
-(one or more hosts, including an MDS, one or more OSTs, and a mountpoint).
-If the MDS and/or OST is on a remote machine, configure them first:
-
- ../utils/lconf --reformat <conf>.xml
-
-On the client machine, the runtests script needs the XML configuration
-file as a command-line parameter, as it mounts and unmounts the filesystem
-several times during the test in order to verify that the data is still
-there as expected (ensures that it makes it to disk instead of just into
-the filesystem cache). If you are running on only a single machine, you
-can just use runtests directly. If this is only a client machine, the
---reformat parameter is not needed (it will not do anything).
-
- sh runtests [--reformat] <conf>.xml
-
-This creates a few simple files and directories first, and then untars
-a copy of the /etc filesystem into the Lustre filesystem. It then does
-data verification both before and after the filesystem is remounted, and
-finally deletes all of the files and verifies that the amount of space
-left in the filesystem is (nearly) the same as it was before the test.
+++ /dev/null
-#!/bin/sh
-# script which _must_ complete successfully (at minimum) before checkins to
-# the CVS HEAD are allowed.
-set -vxe
-
-[ "$CONFIGS" ] || CONFIGS="local lov"
-[ "$THREADS" ] || THREADS=1
-[ "$SIZE" ] || SIZE=20480
-[ "$RSIZE" ] || RSIZE=64
-[ "$UID" ] || UID=1000
-[ "$MNT" ] || MNT=/mnt/lustre
-[ "$TMP" ] || TMP=/tmp
-[ "$COUNT" ] || COUNT=1000
-[ "$DEBUG_OFF" ] || DEBUG_OFF="eval echo 0 > /proc/sys/portals/debug"
-
-for NAME in $CONFIGS; do
- export NAME
- [ -e $NAME.sh ] && sh $NAME.sh
- [ ! -e $NAME.xml ] && echo "no config '$NAME.xml'" 1>&2 && exit 1
-
- if [ "$RUNTESTS" != "no" ]; then
- sh runtests
- fi
-
- mount | grep $MNT || sh llmount.sh
- [ "$SANITY" != "no" ] && sh sanity.sh
- if [ "$DBENCH" != "no" ]; then
- $DEBUG_OFF
- sh rundbench 1
- sh llmountcleanup.sh
- sh llrmount.sh
- if [ $THREADS -gt 1 ]; then
- sh rundbench $THREADS
- sh llmountcleanup.sh
- sh llrmount.sh
- fi
- rm -f /mnt/lustre/client.txt
- fi
- chown $UID $MNT && chmod 700 $MNT
- if [ "$BONNIE" != "no" ]; then
- $DEBUG_OFF
- bonnie++ -s 0 -n 10 -u $UID -d $MNT
- sh llmountcleanup.sh
- sh llrmount.sh
- fi
- IOZONE_OPTS="-i 0 -i 1 -i 2 -+d -r $RSIZE -s $SIZE"
- IOZONE_FILE="-f $MNT/iozone"
- if [ "$IOZONE" != "no" ]; then
- $DEBUG_OFF
- iozone $IOZONE_OPTS $IOZONE_FILE
- sh llmountcleanup.sh
- sh llrmount.sh
- fi
- if [ "$IOZONE_DIR" != "no" ]; then
- $DEBUG_OFF
- iozone -I $IOZONE_OPTS $IOZONE_FILE.odir
- IOZVER=`iozone -v | awk '/Revision:/ { print $3 }' | tr -d '.'`
- sh llmountcleanup.sh
- sh llrmount.sh
- if [ "$THREADS" -gt 1 -a "$IOZVER" -ge 3145 ]; then
- $DEBUG_OFF
- THREAD=1
- IOZONE_FILE="-F "
- SIZE=`expr $SIZE / $THREADS`
- while [ $THREAD -le $THREADS ]; do
- IOZONE_FILE="$IOZONE_FILE $MNT/iozone.$THREAD"
- THREAD=`expr $THREAD + 1`
- done
- iozone -I $IOZONE_OPTS -t $THREADS $IOZONE_FILE
- sh llmountcleanup.sh
- sh llrmount.sh
- elif [ $IOZVER -lt 3145 ]; then
- VER=`iozone -v | awk '/Revision:/ { print $3 }'`
- echo "iozone $VER too old for multi-threaded tests"
- fi
- fi
- if [ "$FSX" != "no" ]; then
- $DEBUG_OFF
- ./fsx -c 50 -p 1000 -P $TMP -l 1024000 -N $(($COUNT * 100)) $MNT/fsxfile
- sh llmountcleanup.sh
- #sh llrmount.sh
- fi
- mount | grep $MNT && sh llmountcleanup.sh
-done
+++ /dev/null
-#!/bin/bash
-
-config=${1:-ba-echo.xml}
-
-LMC="save_cmd"
-LMC_REAL="../../lustre/utils/lmc -m $config"
-
-TCPBUF=1048576
-OST=ba-ost-1
-CLIENT=client
-
-UUIDLIST=${UUIDLIST:-/usr/local/admin/ba-ost/UUID.txt}
-
-h2ip () {
- echo "${1}"
-}
-BATCH=/tmp/lmc-batch.$$
-save_cmd() {
- echo "$@" >> $BATCH
-}
-
-[ -f $config ] && rm $config
-
-# Client node
-${LMC} --node $CLIENT --tcpbuf $TCPBUF --net '*' tcp
-
-OBD_UUID=`awk "/$OST / { print \\$3 }" $UUIDLIST`
-[ "$OBD_UUID" ] && OBD_UUID="--obduuid=$OBD_UUID" || echo "$OST: no UUID"
-
-# server node
-${LMC} --node $OST --tcpbuf $TCPBUF --net $OST tcp
-${LMC} --node $OST --obdtype=obdecho $OBD_UUID --ost
-
-# osc on client
-${LMC} --node $CLIENT --osc OSC_$OST
-
-$LMC_REAL --batch $BATCH
-rm -f $BATCH
+++ /dev/null
-#!/bin/bash
-
-# There are configurations for three machines in this config file: the OST,
-# the MDS/client, other clients
-#
-# To start your cluster using the ba-mount.xml file that this produces, first
-# run:
-# > lconf ba-mount.xml
-# on the MDS/client, and then run:
-# > lconf --node client ba-mount.xml
-# on any other clients.
-
-config=${1:-ba-mount.xml}
-
-LMC_REAL="${LMC:-../utils/lmc} -m $config"
-LMC="save_cmd"
-
-TCPBUF=1048576
-OST=${OST:-ba-ost-1}
-MDS=`hostname`
-
-UUIDLIST=${UUIDLIST:-/usr/local/admin/ba-ost/UUID.txt}
-
-h2ip () {
- echo "${1}"
-}
-BATCH=/tmp/lmc-batch.$$
-save_cmd() {
- echo "$@" >> $BATCH
-}
-
-[ -f $config ] && rm $config
-
-# MDS/client node
-${LMC} --node $MDS --tcpbuf $TCPBUF --net $MDS tcp
-${LMC} --node $MDS --mds mds1 /tmp/mds1 50000
-
-OBD_UUID=`awk "/$OST / { print \\$3 }" $UUIDLIST`
-[ "$OBD_UUID" ] && OBD_UUID="--obduuid=$OBD_UUID" || echo "$OST: no UUID"
-
-# server node
-${LMC} --node $OST --tcpbuf $TCPBUF --net $OST tcp
-${LMC} --node $OST $OBD_UUID --ost bluearc
-
-# mount point on the MDS/client
-${LMC} --node $MDS --mtpt /mnt/lustre mds1 OSC_$OST
-
-# other clients
-${LMC} --node client --tcpbuf $TCPBUF --net '*' tcp
-${LMC} --node client --mtpt /mnt/lustre mds1 OSC_$OST
-
-$LMC_REAL --batch $BATCH
-rm -f $BATCH
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a client to talk to an echo OST
-SETUP_OSC=y
+++ /dev/null
-#!/bin/sh
-# Config file for mounting a client Lustre filesystem
-SETUP_MDC=y
-SETUP_OSC=y
-OSCMT=/mnt/lustre
-SETUP_MOUNT=y
+++ /dev/null
-#!/bin/sh
-# Config file for mounting a client Lustre filesystem
-MDC_NAMES="MDCDEV1 MDCDEV2"
-OSC_NAMES="OSCDEV1 OSCDEV2"
-SETUP_MDC=y
-SETUP_OSC=y
-MT1="/mnt/lustre1 OSCDEV1 MDCDEV1"
-MT2="/mnt/lustre2 OSCDEV2 MDCDEV2"
-MOUNT_LIST="MT1 MT2"
-SETUP_MOUNT=y
+++ /dev/null
-#!/bin/sh
-export PATH=$PATH:/sbin:/usr/sbin
-
-[ -d /r ] && R=/r
-
-# check if running in source directory
-# will probably need to create variable for each module.
-if [ -f $SRCDIR/Makefile.am ]; then
- USEDEV=yes
- PORTALS=$SRCDIR/../../portals
- LUSTRE=$SRCDIR/..
-
- PTLCTL=$LUSTRE/utils/lctl
- DBGCTL=$LUSTRE/utils/lctl
- ACCEPTOR=$PORTALS/linux/utils/acceptor
-
- OBDCTL=$LUSTRE/utils/lctl
-else
- USEDEV=no
- # should have configure set the paths here
- BINDIR=/usr/sbin
- PORTALS=/lib/modules
- LUSTRE=/lib/modules
-
- PTLCTL=$BINDIR/lctl
- DBGCTL=$BINDIR/lctl
- ACCEPTOR=$BINDIR/acceptor
- OBDCTL=$BINDIR/lctl
-fi
-
-LOOPNUM=0; export LOOPNUM
-if [ -b /dev/loop0 ]; then
- LOOP=/dev/loop
-elif [ -b /dev/loop/0 ]; then
- LOOP=/dev/loop/
-else
- echo "Cannot find /dev/loop0 or /dev/loop/0" 1>&2 && exit -1
-fi
-
-do_insmod() {
- MODULE=$1
- BASE=`echo $MODULE | sed -e "s^.*/^^" -e "s/\.o$//"`
-
- lsmod | grep -q "\<$BASE\>" && return 0
- [ "$MODULE" ] || fail "usage: $0 <module>"
-
- if [ "$USEDEV" = "yes" ]; then
- [ -f $MODULE ] || echo "$0: module '$MODULE' not found" 1>&2
- insmod $MODULE
- else
- modprobe $BASE
- fi
-}
-
-do_rmmod() {
- MODULE=$1
- [ "$MODULE" ] || fail "usage: $0 <module>"
- lsmod | grep -q $MODULE || return 0
- rmmod $MODULE || lsmod | sed "s/^/$MODULE failed: /"
-}
-
-# Return the next unused loop device on stdout and in the $LOOPDEV
-# environment variable.
-next_loop_dev() {
- NEXT=
- while [ -b ${LOOP}${LOOPNUM} ]; do
- LOOPDEV=${LOOP}${LOOPNUM}
- losetup ${LOOPDEV} > /dev/null 2>&1 || NEXT=${LOOPDEV}
- LOOPNUM=`expr ${LOOPNUM} + 1`
- [ "$NEXT" ] && echo ${NEXT} && break
- done
-}
-
-# Create a new filesystem. If we are using a loopback device, we check
-# for existing "template" filesystems instead of creating a new one,
-# because it is _much_ faster to gunzip the empty filesystem instead of
-# creating a new one from scratch. Conversely, if we are creating a
-# filesystem on a device we use mkfs, because that only writes sparsely
-# to the device. The empty filesystems are also highly compressed (1000:1)
-# so they don't take too much space.
-#
-new_fs_usage() {
- echo "new_fs <fstype> {device | file} [size]" 1>&2
- exit -1
-}
-new_fs () {
- EFILE="$1_$3.gz"
- MKFS="mkfs.$1"
- MKFSOPT="-b 4096"
-
- [ "$1" = "ext3" ] && MKFS="mkfs.ext2 -j"
- if [ "$1" = "extN" ]; then
- MKFS="mkfs.ext2 -j"
- EFILE="ext3_$3.gz"
- fi
-
- if [ -b "$2" ]; then
- [ $# -lt 2 -o $# -gt 3 ] && new_fs_usage
-
- PM="/proc/mounts"
- [ -r "$PM" ] || PM="/etc/mtab"
-
- grep "$2 " $PM 1>&2 && echo "$0: $2 is in $PM!" 1>&2 && exit -1
-
- $MKFS $MKFSOPT $2 $3 || exit -1
- LOOPDEV=$2 # Not really a loop device
- else
- [ $# -ne 3 ] && new_fs_usage
-
- if [ -r "$EFILE" ]; then
- echo "using prepared filesystem $EFILE for $2"
- zcat "$EFILE" > $2 || exit -1
- sync
- else
- echo "creating new sparse filesystem on $2"
- dd if=/dev/zero of=$2 bs=1k seek=$3 count=1 1>&2 || exit -1
- $MKFS $MKFSOPT -F $2 1>&2 || exit -1
- fi
- LOOPDEV=`next_loop_dev`
- losetup ${LOOPDEV} $2 1>&2 || exit -1
- fi
-
- # Enable hash-indexed directories for extN filesystems
- [ "$1" = "extN" ] && echo "feature FEATURE_C5" | debugfs -w $2
-}
-
-# Set up to use an existing filesystem. We take the same parameters as
-# new_fs, even though we only use the <fstype> and <file> parameters, to
-# make it easy to convert between new_fs and old_fs in testing scripts.
-old_fs () {
- [ -e $2 ] || exit -1
-
- if [ -b "$2" ]; then
- LOOPDEV=$2 # Not really a loop device
- else
- LOOPDEV=`next_loop_dev`
- losetup ${LOOPDEV} $2 1>&2 || exit -1
- fi
-}
-
-list_mods() {
- $DBGCTL modules > $R/tmp/ogdb
- echo "The GDB module script is in $R/tmp/ogdb"
- [ "$DEBUG_WAIT" = "yes" ] && echo -n "Press ENTER to continue" && read < /dev/tty
- return 0
-}
-
-# start acceptor for a given network and port.
-# not all networks need an acceptor
-start_acceptor() {
- case $NETWORK in
- elan) [ "$PORT" ] && fail "$0: NETWORK is elan but PORT is set"
- ;;
- tcp) [ "$PORT" ] || fail "$0: NETWORK is tcp but PORT is not set"
- $ACCEPTOR -r 1048576 -s 1048576 $PORT
- ;;
- *) fail "$0: unknown NETWORK '$NETWORK'" ;;
- esac
-
-}
-
-# We need at least one setup file to be given. It can be passed on
-# the command-line, or it can be found in the home directory, or it
-# can even be sourced into the current shell environment.
-setup_opts() {
- DEF=/etc/lustre/lustre.cfg
- if [ "$#" = 0 -a -r $DEF ]; then
- . $DEF && SETUP=y
- fi
-
- for CFG in "$@" ; do
- case $CFG in
- *.cfg) [ -r "$CFG" ] && . $CFG && SETUP=y ;;
- *) echo "unknown option '$CFG'" 1>&2
- esac
- done
-
- if [ "$SETUP" != "y" ]; then
- echo "error: no config file on command-line and no $DEF" 1>&2
- exit -1
- fi
-
- [ "$MDC_NAMES" ] || export MDC_NAMES=MDCDEV
- [ "$OSC_NAMES" ] || export OSC_NAMES=OSCDEV
- [ -z "$MOUNT_LIST" -a "$OSCMT" ] && export MOUNT_LIST="MT" && export MT="$OSCMT OSCDEV MDCDEV"
-}
-
-setup_variables() {
- [ -z "$OSTNODE" ] && OSTNODE=$SERVER
- [ -z "$MDSNODE" ] && MDSNODE=$SERVER
- [ -z "$DLM" ] && DLM=$SERVER
-}
-
-setup_portals() {
- setup_variables
-
- if egrep -q "ksocknal|kqswnal" /proc/modules; then
- echo "$0: portals already appears to be set up, skipping"
- return 0
- fi
-
- if [ -z "$NETWORK" -o -z "$LOCALHOST" ]; then
- echo "$0: NETWORK or LOCALHOST is not set" 1>&2
- exit -1
- fi
-
- if [ -z "$OSTNODE" -a -z "$MDSNODE" -a -z "$DLM" ]; then
- echo "$0: SERVER (or OSTNODE and MDSNODE and DLM) not set" 1>&2
- exit -1
- fi
-
- [ -c /dev/portals ] || mknod /dev/portals c 10 240
-
- do_insmod $PORTALS/linux/oslib/portals.o || exit -1
- #do_insmod $PORTALS/linux/router/kptlrouter.o || exit -1
-
- case $NETWORK in
- elan) do_insmod $PORTALS/linux/rqswnal/kqswnal.o || exit -1
- MYNID=
- RECV_MEM=
- SEND_MEM=
- ;;
- tcp) do_insmod $PORTALS/linux/socknal/ksocknal.o || exit -1
- MYNID="mynid $LOCALHOST"
- RECV_MEM="recv_mem 1048576"
- SEND_MEM="send_mem 1048576"
- ;;
- *) fail "$0: unknown NETWORK '$NETWORK'" ;;
- esac
-
- start_acceptor
-
- $PTLCTL <<- EOF
- network $NETWORK
- $SEND_MEM
- $RECV_MEM
- $MYNID
- connect $DLM $PORT
- add_uuid $DLM $DLM
- add_uuid self $LOCALHOST
- quit
- EOF
-
- if [ "$SETUP_MDS" -o "$SETUP_MDC" ]; then
- $PTLCTL <<- EOF
- network $NETWORK
- connect $MDSNODE $PORT
- add_uuid $MDSNODE $MDSNODE
- quit
- EOF
- fi
-
-
- if [ "$SETUP_OST" -o "$SETUP_OSC" ]; then
- $PTLCTL <<- EOF
- network $NETWORK
- connect $OSTNODE $PORT
- add_uuid $OSTNODE $OSTNODE
- quit
- EOF
- fi
-}
-
-setup_lustre() {
- [ -c /dev/obd ] || mknod /dev/obd c 10 241
-
- do_insmod $LUSTRE/obdclass/obdclass.o || exit -1
- do_insmod $LUSTRE/ptlrpc/ptlrpc.o || exit -1
- do_insmod $LUSTRE/ldlm/ldlm.o || exit -1
- do_insmod $LUSTRE/extN/extN.o || \
- echo "info: can't load extN.o module, not fatal if using ext3"
- do_insmod $LUSTRE/mds/mds.o || exit -1
- #do_insmod $LUSTRE/mds/mds_ext2.o || exit -1
- #do_insmod $LUSTRE/mds/mds_ext3.o || exit -1
- do_insmod $LUSTRE/mds/mds_extN.o || \
- echo "info: can't load mds_extN.o module, needs extN.o"
- do_insmod $LUSTRE/obdecho/obdecho.o || exit -1
- #do_insmod $LUSTRE/obdext2/obdext2.o || exit -1
- do_insmod $LUSTRE/obdfilter/obdfilter.o || exit -1
- do_insmod $LUSTRE/ost/ost.o || exit -1
- do_insmod $LUSTRE/osc/osc.o || exit -1
- do_insmod $LUSTRE/mdc/mdc.o || exit -1
- do_insmod $LUSTRE/lov/lov.o || exit -1
- do_insmod $LUSTRE/llite/llite.o || exit -1
-
- echo "$R/tmp/lustre-log" > /proc/sys/portals/debug_path
-
- if $OBDCTL name2dev RPCDEV > /dev/null 2>&1; then
- echo "$0: RPCDEV is already configured, skipping"
- return 0
- fi
- list_mods
-
- $OBDCTL <<- EOF || return $?
- newdev
- attach ptlrpc RPCDEV
- setup
- quit
- EOF
-
- [ -d /mnt/lustre ] || mkdir /mnt/lustre
-}
-
-setup_ldlm() {
- [ "$SETUP_LDLM" = "y" ] || return 0
-
- [ -c /dev/portals ] || mknod /dev/portals c 10 240
-
- $OBDCTL <<- EOF || return $?
- newdev
- attach ldlm LDLMDEV LDLMUUID
- setup
- quit
- EOF
-}
-
-find_devno() {
- if [ -z "$1" ]; then
- echo "usage: $0 <devname>" 1>&2
- return -1
- fi
-
- $OBDCTL name2dev $1
-}
-
-setup_mds() {
- [ "$SETUP_MDS" = "y" ] || return 0
-
- if [ -z "$MDSFS" -o -z "$MDSDEV" ]; then
- echo "error: setup_mds: MDSFS or MDSDEV unset" 1>&2
- return -1
- fi
-
- [ "$1" ] && DO_FS=$1
- if [ "$DO_FS" != "new_fs" -a "$DO_FS" != "old_fs" ]; then
- echo "usage: setup_mds {new_fs|old_fs}" 1>&2
- return -1
- fi
-
- if $OBDCTL name2dev MDSDEV > /dev/null 2>&1; then
- echo "$0: MDSDEV is already configured"
- return 0
- fi
-
- $DO_FS ${MDSFS} ${MDSDEV} ${MDSSIZE}
- MDS=${LOOPDEV}
-
- $OBDCTL <<- EOF || return $?
- newdev
- attach mds MDSDEV MDSUUID
- setup ${MDS} ${MDSFS}
- quit
- EOF
-}
-
-setup_mds_lov() {
- [ "$SETUP_MDS" = "y" ] || return 0
-
- if [ -z "$LOVUUID" ]; then
- echo "No LOV configured"
- return
- fi
-
- $OBDCTL <<- EOF || return $?
- name2dev MDSDEV
- connect
- lov_setconfig ${LOVUUID} 1 65536 0 OSCDEV-`hostname`
- disconnect
- quit
- EOF
-}
-
-
-setup_ost() {
- [ "$SETUP_OST" = "y" ] || return 0
-
- if [ -z "$OSTTYPE" ]; then
- echo "error: setup_ost: OSTTYPE unset" 1>&2
- return -1
- fi
-
- case $OSTTYPE in
- obdecho) OBD=
- OBDARG=
- NEED_FS=n
- ;;
- obdext2) OBDARG=
- NEED_FS=y
- ;;
- obdfilter) OBDARG=$OSTFS
- NEED_FS=y
- ;;
- *) echo "error: setup_ost: unknown OSTTYPE '$OSTTYPE'" 1>&2
- return -1
- ;;
- esac
-
- if $OBDCTL name2dev OBDDEV > /dev/null 2>&1; then
- echo "$0: OBDDEV is already configured"
- return 0
- fi
-
- if [ "$NEED_FS" = "y" ]; then
- [ "$1" ] && DO_FS=$1
- if [ -z "$OSTFS" -o -z "$OSTDEV" ]; then
- echo "error: setup_ost: OSTFS or OSTDEV unset" 1>&2
- return -1
- fi
-
- if [ "$DO_FS" != "new_fs" -a "$DO_FS" != "old_fs" ]; then
- echo "usage: setup_ost {new_fs|old_fs}" 1>&2
- return -1
- fi
-
- $DO_FS ${OSTFS} ${OSTDEV} ${OSTSIZE}
- OBD=${LOOPDEV}
- fi
-
- $OBDCTL <<- EOF || return $?
- newdev
- attach ${OSTTYPE} OBDDEV OBDUUID
- setup ${OBD} ${OBDARG}
- quit
- EOF
-
- $OBDCTL <<- EOF || return $?
- newdev
- attach ost OSTDEV OSTUUID
- setup OBDUUID
- quit
- EOF
-}
-
-setup_server() {
- #setup_mds $1 && setup_mds_lov $1 && setup_ost $1
- setup_mds $1 && setup_ost $1
-}
-
-setup_osc() {
- [ "$SETUP_OSC" != "y" ] && return 0
- [ "$OSC_NAMES" ] || OSC_NAMES=OSCDEV
-
- for THEOSC in $OSC_NAMES ; do
- if $OBDCTL name2dev $THEOSC > /dev/null 2>&1; then
- echo "$0: OSCDEV is already configured"
- continue
- fi
-
- [ -z "$OBD_UUID" ] && OBD_UUID="OBDUUID"
- $OBDCTL <<- EOF || return $rc
- newdev
- attach osc $THEOSC ${THEOSC}-`hostname`
- setup $OBD_UUID $OSTNODE
- quit
- EOF
- done
-}
-
-setup_mdc() {
- [ "$SETUP_MDC" != "y" ] && return 0
- [ "$MDC_NAMES" ] || MDC_NAMES=MDCDEV
-
- for THEMDC in $MDC_NAMES ; do
- if $OBDCTL name2dev $THEMDC > /dev/null 2>&1; then
- echo "$0: MDCDEV is already configured"
- continue
- fi
-
- $OBDCTL <<- EOF || return $?
- newdev
- attach mdc $THEMDC ${THEMDC}-`hostname`
- setup MDSUUID $MDSNODE
- quit
- EOF
- done
-}
-
-setup_lov () {
- [ "$SETUP_MDC" != "y" ] && return 0
-
- if [ -z "$LOVUUID" ]; then
- echo "No LOV configured"
- return
- fi
-
- $OBDCTL <<- EOF || return $?
- newdev
- attach lov LOVNAME ${LOVUUID}
- setup MDCDEV-`hostname`
- quit
- EOF
-}
-
-
-setup_mount() {
- [ "$SETUP_MOUNT" != "y" ] && return 0
-
- [ "$MOUNT_LIST" ] || fail "error: $0: MOUNT_LIST unset"
-
- for THEMOUNT in $MOUNT_LIST; do
- eval "echo \$$THEMOUNT" | while read MTPT THEOSC THEMDC; do
- if mount | grep -q $MTPT; then
- echo "$0: $MTPT is already mounted"
- return 0
- fi
-
- [ ! -d $MTPT ] && mkdir $MTPT
- echo mount -t lustre_lite -o osc=${THEOSC}-`hostname`,mdc=${THEMDC}-`hostname` none $MTPT
- mount -t lustre_lite -o osc=${THEOSC}-`hostname`,mdc=${THEMDC}-`hostname` none $MTPT
- done
- done
-}
-
-setup_client() {
- # setup_osc && setup_mdc && setup_lov && setup_mount
- setup_osc && setup_mdc && setup_mount
-}
-
-DEBUG_ON="echo 0xffffffff > /proc/sys/portals/debug"
-DEBUG_OFF="echo 0 > /proc/sys/portals/debug"
-
-debug_server_off() {
- echo "Turn OFF debug" && eval "$DEBUG_OFF"
-}
-
-debug_server_on() {
- echo "Turn ON debug" && eval "$DEBUG_ON"
-}
-
-debug_client_off() {
- echo "Turning OFF debug on client" && eval "$DEBUG_OFF"
-}
-
-debug_client_on() {
- echo "Turning ON debug on client" && eval "$DEBUG_ON"
-}
-
-cleanup_portals() {
- [ -z "$NETWORK" ] && NETWORK=tcp
-
- setup_variables
-
- $PTLCTL <<- EOF
- network $NETWORK
- disconnect
- del_uuid self
- del_uuid $MDSNODE
- del_uuid $OSTNODE
- del_uuid $DLM
- quit
- EOF
-
- do_rmmod ldlm
- do_rmmod ptlrpc
- do_rmmod obdclass
-
- do_rmmod kqswnal
- do_rmmod ksocknal
- do_rmmod kptlrouter
-
- [ "$TIME" ] && $DBGCTL debug_kernel $R/tmp/debug.5.$TIME
-
- do_rmmod portals
-}
-
-cleanup_lustre() {
- killall acceptor
-
- do_rmmod llite
- do_rmmod lov
- do_rmmod mdc
- do_rmmod osc
-
- do_rmmod mds_extN
- do_rmmod mds_ext3
- do_rmmod mds_ext2
- do_rmmod mds
- do_rmmod ost
- do_rmmod obdecho
- do_rmmod obdfilter
- do_rmmod obdext2
- do_rmmod extN
-
- losetup -d ${LOOP}0
- losetup -d ${LOOP}1
- losetup -d ${LOOP}2
-}
-
-cleanup_ldlm() {
- [ "$SETUP" -a -z "$SETUP_LDLM" ] && return 0
-
- LDLMDEVNO=`find_devno LDLMDEV`
- if [ "$LDLMDEVNO" ]; then
- $OBDCTL <<- EOF
- device $LDLMDEVNO
- cleanup
- detach
- quit
- EOF
- fi
-}
-
-cleanup_mds() {
- [ "$SETUP" -a -z "$SETUP_MDS" ] && return 0
-
- MDSDEVNO=`find_devno MDSDEV`
- if [ "$MDSDEVNO" ]; then
- $OBDCTL <<- EOF
- device $MDSDEVNO
- cleanup
- detach
- quit
- EOF
- fi
-}
-
-cleanup_ost() {
- [ "$SETUP" -a -z "$SETUP_OST" ] && return 0
-
- OSTDEVNO=`find_devno OSTDEV`
- if [ "$OSTDEVNO" ]; then
- $OBDCTL <<- EOF
- device $OSTDEVNO
- cleanup
- detach
- quit
- EOF
- fi
-
- OBDDEVNO=`find_devno OBDDEV`
- if [ "$OBDDEVNO" ]; then
- $OBDCTL <<- EOF
- device $OBDDEVNO
- cleanup
- detach
- quit
- EOF
- fi
-}
-
-cleanup_server() {
- cleanup_ost && cleanup_mds
-}
-
-cleanup_mount() {
- [ "$SETUP_MOUNT" != "y" ] && return 0
-
- [ "$MOUNT_LIST" ] || fail "error: $0: MOUNT_LIST unset"
-
- for THEMOUNT in $MOUNT_LIST; do
- eval "echo \$$THEMOUNT" | while read MTPT THEOSC THEMDC; do
- if [ "`mount | grep $MTPT`" ]; then
- umount $MTPT || fail "unable to unmount $MTPT"
- fi
- done
- done
-}
-
-cleanup_osc() {
- [ "$SETUP" -a -z "$SETUP_OSC" ] && return 0
- [ "$OSC_NAMES" ] || OSC_NAMES=OSCDEV
-
- for THEOSC in $OSC_NAMES ; do
- OSCDEVNO=`find_devno $THEOSC`
- if [ "$OSCDEVNO" ]; then
- $OBDCTL <<- EOF
- device $OSCDEVNO
- cleanup
- detach
- quit
- EOF
- fi
- done
-}
-
-cleanup_mdc() {
- [ "$SETUP" -a -z "$SETUP_MDC" ] && return 0
- [ "$MDC_NAMES" ] || MDC_NAMES=MDCDEV
-
- for THEMDC in $MDC_NAMES ; do
- MDCDEVNO=`find_devno $THEMDC`
- if [ "$MDCDEVNO" ]; then
- $OBDCTL <<- EOF
- device $MDCDEVNO
- cleanup
- detach
- quit
- EOF
- fi
- done
-}
-
-cleanup_rpc() {
- RPCDEVNO=`find_devno RPCDEV`
- if [ "$RPCDEVNO" ]; then
- $OBDCTL <<- EOF
- device $RPCDEVNO
- cleanup
- detach
- quit
- EOF
- fi
-}
-
-cleanup_client() {
- cleanup_mount && cleanup_osc && cleanup_mdc && cleanup_rpc
-}
-
-fail() {
- echo "ERROR: $1" 1>&2
- [ $2 ] && RC=$2 || RC=1
- exit $RC
-}
+++ /dev/null
-#!/usr/bin/perl
-use Getopt::Long;
-
-GetOptions("silent!"=> \$silent);
-
-my $mtpt = shift || usage();
-my $mount_count = shift || usage();
-my $i = shift || usage();
-my $files = 5;
-my $mcreate = 0; # should we use mcreate or open?
-
-sub usage () {
- print "Usage: $0 <mount point prefix> <mount count> <iterations>\n";
- print "example: $0 /mnt/lustre 2 50\n";
- print " will test in /mnt/lustre1 and /mnt/lustre2\n";
- print " $0 /mnt/lustre -1 50\n";
- print " will test in /mnt/lustre only\n";
- exit;
-}
-
-sub do_open($) {
- my $path = shift;
-
- if ($mcreate) {
- my $tmp = `./mcreate $path`;
- if ($tmp) {
- print "Creating $path [" . $$."]...\n" if !$silent;
- $tmp =~ /.*error: (.*)\n/;
- print "Create done [$$] $path: $!\n" if !$silent;
- } else {
- print "Create done [$$] $path: Success\n"if !$silent;
- }
- } else {
- print "Opening $path [" . $$."]...\n"if !$silent;
- open(FH, ">$path") || die "open($PATH): $!";
- print "Open done [$$] $path: Success\n"if !$silent;
- close(FH) || die;
- }
-}
-
-while ($i--) {
- my $which = "";
- if ($mount_count > 0) {
- $which = int(rand() * $mount_count) + 1;
- }
- $d = int(rand() * $files);
- do_open("$mtpt$which/$d");
-
- if ($mount_count > 0) {
- $which = int(rand() * $mount_count) + 1;
- }
- $d = int(rand() * $files);
- $path = "$mtpt$which/$d";
- print "Unlink $path start [" . $$."]...\n"if !$silent;
- if (unlink($path)) {
- print "Unlink done [$$] $path: Success\n"if !$silent;
- } else {
- print "Unlink done [$$] $path: $!\n"if !$silent;
- }
-}
-print "Done.\n";
+++ /dev/null
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <sys/time.h>
-
-int thread;
-
-#define BAD_VERBOSE (-999999999)
-
-#define difftime(a, b) \
- ((double)(a)->tv_sec - (b)->tv_sec + \
- ((double)((a)->tv_usec - (b)->tv_usec) / 1000000))
-
-static char *cmdname(char *func)
-{
- static char buf[512];
-
- if (thread) {
- sprintf(buf, "%s-%d", func, thread);
- return buf;
- }
-
- return func;
-}
-
-static int be_verbose(int verbose, struct timeval *next_time,
- unsigned long num, unsigned long *next_num, int num_total)
-{
- struct timeval now;
-
- if (!verbose)
- return 0;
-
- if (next_time != NULL)
- gettimeofday(&now, NULL);
-
- /* A positive verbosity means to print every X iterations */
- if (verbose > 0 &&
- (next_num == NULL || num >= *next_num || num >= num_total)) {
- *next_num += verbose;
- if (next_time) {
- next_time->tv_sec = now.tv_sec - verbose;
- next_time->tv_usec = now.tv_usec;
- }
- return 1;
- }
-
- /* A negative verbosity means to print at most each X seconds */
- if (verbose < 0 && next_time != NULL && difftime(&now, next_time) >= 0){
- next_time->tv_sec = now.tv_sec - verbose;
- next_time->tv_usec = now.tv_usec;
- if (next_num)
- *next_num = num;
- return 1;
- }
-
- return 0;
-}
-
-static int get_verbose(char *func, const char *arg)
-{
- int verbose;
- char *end;
-
- if (!arg || arg[0] == 'v')
- verbose = 1;
- else if (arg[0] == 's' || arg[0] == 'q')
- verbose = 0;
- else {
- verbose = (int)strtoul(arg, &end, 0);
- if (*end) {
- fprintf(stderr, "%s: error: bad verbose option '%s'\n",
- func, arg);
- return BAD_VERBOSE;
- }
- }
-
- if (verbose < 0)
- printf("Print status every %d seconds\n", -verbose);
- else if (verbose == 1)
- printf("Print status every operation\n");
- else if (verbose > 1)
- printf("Print status every %d operations\n", verbose);
-
- return verbose;
-}
-
-int main(int argc, char *argv[])
-{
- char filename[1024];
- int verbose = 0;
- unsigned long count, i;
- int threads = 0;
- char *end;
- int rc;
-
- if (argc < 3 || argc > 5) {
- fprintf(stderr,
- "usage: %s <filename> <count> [verbose [threads]]\n",
- argv[0]);
- exit(1);
- }
-
- count = strtoul(argv[2], &end, 0);
- if (*end) {
- fprintf(stderr, "%s: error: bad iteration count '%s'\n",
- argv[0], argv[1]);
- exit(2);
- }
- if (argc == 4) {
- verbose = get_verbose(argv[0], argv[3]);
- if (verbose == BAD_VERBOSE)
- exit(2);
- }
- if (argc == 5) {
- threads = strtoul(argv[4], &end, 0);
- if (*end) {
- fprintf(stderr, "%s: error: bad thread count '%s'\n",
- argv[0], argv[1]);
- exit(2);
- }
- }
-
- for (i = 1; i <= threads; i++) {
- rc = fork();
- if (rc < 0) {
- fprintf(stderr, "%s: error: #%ld - %s\n",
- cmdname(argv[0]), i, strerror(rc = errno));
- break;
- } else if (rc == 0) {
- thread = i;
- break;
- } else
- printf("%s: thread #%ld (PID %d) started\n",
- cmdname(argv[0]), i, rc);
- rc = 0;
- }
-
- if (threads && thread == 0) { /* parent process */
- int live_threads = threads;
-
- while (live_threads > 0) {
- int status;
- pid_t ret;
-
- ret = waitpid(0, &status, 0);
- if (ret == 0) {
- continue;
- }
-
- if (ret < 0) {
- fprintf(stderr, "%s: error: wait - %s\n",
- argv[0], strerror(errno));
- if (!rc)
- rc = errno;
- } else {
- /*
- * This is a hack. We _should_ be able to use
- * WIFEXITED(status) to see if there was an
- * error, but it appears to be broken and it
- * always returns 1 (OK). See wait(2).
- */
- int err = WEXITSTATUS(status);
- if (err || WIFSIGNALED(status))
- fprintf(stderr,
- "%s: error: PID %d had rc=%d\n",
- argv[0], ret, err);
- if (!rc)
- rc = err;
-
- live_threads--;
- }
- }
- } else {
- struct timeval start, end, next_time;
- unsigned long next_count;
- double diff;
-
- gettimeofday(&start, NULL);
- next_time.tv_sec = start.tv_sec - verbose;
- next_time.tv_usec = start.tv_usec;
-
- for (i = 0, next_count = verbose; i < count; i++) {
- if (threads)
- sprintf(filename, "%s-%d-%ld",
- argv[1], thread, i);
- else
- sprintf(filename, "%s-%ld", argv[1], i);
-
- rc = mknod(filename, S_IFREG, 0);
- if (rc < 0) {
- fprintf(stderr, "%s: error: mknod(%s): %s\n",
- cmdname(argv[0]), filename,
- strerror(errno));
- rc = errno;
- break;
- }
- if (unlink(filename) < 0) {
- fprintf(stderr, "%s: error: unlink(%s): %s\n",
- cmdname(argv[0]), filename,
- strerror(errno));
- rc = errno;
- break;
- }
- if (be_verbose(verbose, &next_time,i,&next_count,count))
- printf("%s: number %ld\n", cmdname(argv[0]), i);
- }
-
- gettimeofday(&end, NULL);
- diff = difftime(&end, &start);
-
- printf("%s: %ldx2 files in %.4gs (%.4g ops/s): rc = %d: %s",
- cmdname(argv[0]), i, diff, (double)i * 2 / diff,
- rc, ctime(&end.tv_sec));
- }
- return rc;
-}
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-int main(int argc, char ** argv)
-{
- int i, rc, count;
- char filename[4096];
-
- if (argc < 3) {
- printf("Usage %s filenamebase count\n", argv[0]);
- return 1;
- }
-
- if (strlen(argv[1]) > 4080) {
- printf("name too long\n");
- return 1;
- }
-
- count = strtoul(argv[2], NULL, 0);
-
- for (i=0 ; i < count ; i++) {
- sprintf(filename, "%s-%d", argv[1], i);
- rc = mknod(filename, S_IFREG| 0444, 0);
- if (rc) {
- printf("mknod(%s) error: %s\n",
- filename, strerror(errno));
- break;
- }
- if ((i % 10000) == 0)
- printf(" - created %d (time %ld)\n", i, time(0));
- }
- return rc;
-}
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/mman.h>
-
-// not correctly in the headers yet!!
-#ifndef O_DIRECT
-#define O_DIRECT 040000 /* direct disk access hint */
-#endif
-
-#define BLOCKSIZE 4096
-
-int main(int argc, char **argv)
-{
- int fd;
- char *buf;
- int pages;
- int rc;
-
- if (argc != 3) {
- printf("Usage: %s file nr_pages\n", argv[0]);
- return 1;
- }
-
- pages = strtoul(argv[2], 0, 0);
- printf("directio on %s for %d pages \n", argv[1], pages);
-
- buf = mmap(0, pages * BLOCKSIZE, PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANON, 0, 0);
- if (!buf) {
- printf("No memory %s\n", strerror(errno));
- return 1;
- }
-
- fd = open(argv[1], O_DIRECT | O_RDWR | O_CREAT);
- if (fd == -1) {
- printf("Cannot open %s: %s\n", argv[1], strerror(errno));
- return 1;
- }
-
- rc = read(fd, buf, pages * BLOCKSIZE);
- if (rc != pages * BLOCKSIZE) {
- printf("Read error: %s, rc %d\n", strerror(errno), rc);
- return 1;
- }
-
- if ( lseek(fd, 0, SEEK_SET) != 0 ) {
- printf("Cannot seek %s\n", strerror(errno));
- return 1;
- }
-
- rc = write(fd, buf, pages * BLOCKSIZE);
- if (rc != pages * BLOCKSIZE) {
- printf("Write error %s\n", strerror(errno));
- return 1;
- }
-
- return 0;
-}
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a remote server with a real OST
-NETWORK=elan
-LOCALHOST=5
-SERVER=4
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a remote server with a real OST
-NETWORK=elan
-LOCALHOST=4
-SERVER=4
+++ /dev/null
-#! /bin/bash
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-#!/bin/sh
-
-R=/r
-
-insmod /lib/modules/2.4.17/kernel/drivers/block/loop.o
-dd if=/dev/zero of=/tmp/fs bs=1024 count=10000
-mke2fs -b 4096 -F /tmp/fs
-losetup /dev/loop/0 /tmp/fs
-
-insmod $R/usr/src/lustre/obdclass/obdclass.o
-insmod $R/usr/src/lustre/obdext2/obdext2.o
-mknod /dev/obd c 10 241
-
-$R/usr/src/lustre/utils/obdctl <<EOF
-device 0
-attach obdext2 OBDEXT2DEV
-setup /dev/loop/0
-quit
-EOF
-
-insmod $R/usr/src/lustre/obdfs/obdfs.o
-mount -t obdfs -o device=0 none /mnt
+++ /dev/null
-/*
- * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License"). You may not use this file except in compliance with the
- * License. Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- *
- * File: fsx.c
- * Author: Avadis Tevanian, Jr.
- *
- * File system exerciser.
- *
- * Rewrite and enhancements 1998-2001 Conrad Minshall -- conrad@mac.com
- *
- * Various features from Joe Sokol, Pat Dirks, and Clark Warner.
- *
- * Small changes to work under Linux -- davej@suse.de
- *
- * Sundry porting patches from Guy Harris 12/2001
- * $FreeBSD: src/tools/regression/fsx/fsx.c,v 1.1 2001/12/20 04:15:57 jkh Exp $
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#if defined(_UWIN) || defined(__linux__)
-# include <sys/param.h>
-# include <limits.h>
-# include <time.h>
-# include <strings.h>
-# include <sys/time.h>
-#endif
-#include <fcntl.h>
-#include <sys/mman.h>
-#ifndef MAP_FILE
-# define MAP_FILE 0
-#endif
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <errno.h>
-
-#define NUMPRINTCOLUMNS 32 /* # columns of data to print on each line */
-
-/*
- * A log entry is an operation and a bunch of arguments.
- */
-
-struct log_entry {
- int operation;
- struct timeval tv;
- int args[3];
-};
-
-#define LOGSIZE 1000
-
-struct log_entry oplog[LOGSIZE]; /* the log */
-int logptr = 0; /* current position in log */
-int logcount = 0; /* total ops */
-
-/*
- * Define operations
- */
-
-#define OP_READ 1
-#define OP_WRITE 2
-#define OP_TRUNCATE 3
-#define OP_CLOSEOPEN 4
-#define OP_MAPREAD 5
-#define OP_MAPWRITE 6
-#define OP_SKIPPED 7
-
-int page_size;
-int page_mask;
-
-char *original_buf; /* a pointer to the original data */
-char *good_buf; /* a pointer to the correct data */
-char *temp_buf; /* a pointer to the current data */
-char *fname; /* name of our test file */
-char logfile[1024]; /* name of our log file */
-char goodfile[1024]; /* name of our test file */
-int fd; /* fd for our test file */
-
-off_t file_size = 0;
-off_t biggest = 0;
-char state[256];
-unsigned long testcalls = 0; /* calls to function "test" */
-
-unsigned long simulatedopcount = 0; /* -b flag */
-int closeprob = 0; /* -c flag */
-int debug = 0; /* -d flag */
-unsigned long debugstart = 0; /* -D flag */
-unsigned long maxfilelen = 256 * 1024; /* -l flag */
-int sizechecks = 1; /* -n flag disables them */
-int maxoplen = 64 * 1024; /* -o flag */
-int quiet = 0; /* -q flag */
-unsigned long progressinterval = 0; /* -p flag */
-int readbdy = 1; /* -r flag */
-int style = 0; /* -s flag */
-int truncbdy = 1; /* -t flag */
-int writebdy = 1; /* -w flag */
-long monitorstart = -1; /* -m flag */
-long monitorend = -1; /* -m flag */
-int lite = 0; /* -L flag */
-long numops = -1; /* -N flag */
-int randomoplen = 1; /* -O flag disables it */
-int seed = 1; /* -S flag */
-int mapped_writes = 1; /* -W flag disables */
-int mapped_reads = 1; /* -R flag disables it */
-int fsxgoodfd = 0;
-FILE * fsxlogf = NULL;
-int badoff = -1;
-int closeopen = 0;
-
-
-void
-vwarnc(code, fmt, ap)
- int code;
- const char *fmt;
- va_list ap;
-{
- fprintf(stderr, "fsx: ");
- if (fmt != NULL) {
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, ": ");
- }
- fprintf(stderr, "%s\n", strerror(code));
-}
-
-
-void
-warn(const char * fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- vwarnc(errno, fmt, ap);
- va_end(ap);
-}
-
-
-void
-prt(char *fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- vfprintf(stdout, fmt, args);
- if (fsxlogf)
- vfprintf(fsxlogf, fmt, args);
- va_end(args);
-}
-
-void
-prterr(char *prefix)
-{
- prt("%s%s%s\n", prefix, prefix ? ": " : "", strerror(errno));
-}
-
-
-void
-log4(int operation, int arg0, int arg1, int arg2, struct timeval *tv)
-{
- struct log_entry *le;
-
- le = &oplog[logptr];
- le->tv = *tv;
- le->operation = operation;
- if (closeopen)
- le->operation = ~ le->operation;
- le->args[0] = arg0;
- le->args[1] = arg1;
- le->args[2] = arg2;
- logptr++;
- logcount++;
- if (logptr >= LOGSIZE)
- logptr = 0;
-}
-
-
-void
-logdump(void)
-{
- int i, count, down;
- struct log_entry *lp;
-
- prt("LOG DUMP (%d total operations):\n", logcount);
- if (logcount < LOGSIZE) {
- i = 0;
- count = logcount;
- } else {
- i = logptr;
- count = LOGSIZE;
- }
- for ( ; count > 0; count--) {
- int opnum;
-
- opnum = i+1 + (logcount/LOGSIZE)*LOGSIZE;
- lp = &oplog[i];
- prt("%d(%d mod 256): %lu.%lu ", opnum, opnum%256,
- lp->tv.tv_sec, lp->tv.tv_usec);
- if ((closeopen = lp->operation < 0))
- lp->operation = ~ lp->operation;
-
- switch (lp->operation) {
- case OP_MAPREAD:
- prt("MAPREAD\t0x%x thru 0x%x\t(0x%x bytes)",
- lp->args[0], lp->args[0] + lp->args[1] - 1,
- lp->args[1]);
- if (badoff >= lp->args[0] && badoff <
- lp->args[0] + lp->args[1])
- prt("\t***RRRR***");
- break;
- case OP_MAPWRITE:
- prt("MAPWRITE 0x%x thru 0x%x\t(0x%x bytes)",
- lp->args[0], lp->args[0] + lp->args[1] - 1,
- lp->args[1]);
- if (badoff >= lp->args[0] && badoff <
- lp->args[0] + lp->args[1])
- prt("\t******WWWW");
- break;
- case OP_READ:
- prt("READ\t0x%x thru 0x%x\t(0x%x bytes)",
- lp->args[0], lp->args[0] + lp->args[1] - 1,
- lp->args[1]);
- if (badoff >= lp->args[0] &&
- badoff < lp->args[0] + lp->args[1])
- prt("\t***RRRR***");
- break;
- case OP_WRITE:
- prt("WRITE\t0x%x thru 0x%x\t(0x%x bytes)",
- lp->args[0], lp->args[0] + lp->args[1] - 1,
- lp->args[1]);
- if (lp->args[0] > lp->args[2])
- prt(" HOLE");
- else if (lp->args[0] + lp->args[1] > lp->args[2])
- prt(" EXTEND");
- if ((badoff >= lp->args[0] || badoff >=lp->args[2]) &&
- badoff < lp->args[0] + lp->args[1])
- prt("\t***WWWW");
- break;
- case OP_TRUNCATE:
- down = lp->args[0] < lp->args[1];
- prt("TRUNCATE %s\tfrom 0x%x to 0x%x",
- down ? "DOWN" : "UP", lp->args[1], lp->args[0]);
- if (badoff >= lp->args[!down] &&
- badoff < lp->args[!!down])
- prt("\t******WWWW");
- break;
- case OP_SKIPPED:
- prt("SKIPPED (no operation)");
- break;
- default:
- prt("BOGUS LOG ENTRY (operation code = %d)!",
- lp->operation);
- }
- if (closeopen)
- prt("\n\t\tCLOSE/OPEN");
- prt("\n");
- i++;
- if (i == LOGSIZE)
- i = 0;
- }
-}
-
-
-void
-save_buffer(char *buffer, off_t bufferlength, int fd)
-{
- off_t ret;
- ssize_t byteswritten;
-
- if (fd <= 0 || bufferlength == 0)
- return;
-
- if (bufferlength > SSIZE_MAX) {
- prt("fsx flaw: overflow in save_buffer\n");
- exit(67);
- }
- if (lite) {
- off_t size_by_seek = lseek(fd, (off_t)0, SEEK_END);
- if (size_by_seek == (off_t)-1)
- prterr("save_buffer: lseek eof");
- else if (bufferlength > size_by_seek) {
- warn("save_buffer: .fsxgood file too short... will
-save 0x%llx bytes instead of 0x%llx\n", (unsigned long long)size_by_seek,
- (unsigned long long)bufferlength);
- bufferlength = size_by_seek;
- }
- }
-
- ret = lseek(fd, (off_t)0, SEEK_SET);
- if (ret == (off_t)-1)
- prterr("save_buffer: lseek 0");
-
- byteswritten = write(fd, buffer, (size_t)bufferlength);
- if (byteswritten != bufferlength) {
- if (byteswritten == -1)
- prterr("save_buffer write");
- else
- warn("save_buffer: short write, 0x%x bytes instead
-of 0x%llx\n",
- (unsigned)byteswritten,
- (unsigned long long)bufferlength);
- }
-}
-
-
-void
-report_failure(int status)
-{
- logdump();
-
- if (fsxgoodfd) {
- if (good_buf) {
- save_buffer(good_buf, file_size, fsxgoodfd);
- prt("Correct content saved for comparison\n");
- prt("(maybe hexdump \"%s\" vs \"%s\")\n",
- fname, goodfile);
- }
- close(fsxgoodfd);
- }
- exit(status);
-}
-
-
-#define short_at(cp) ((unsigned short)((*((unsigned char *)(cp)) << 8) | \
- *(((unsigned char *)(cp)) + 1)))
-
-void
-check_buffers(unsigned offset, unsigned size)
-{
- unsigned char c, t;
- unsigned i = 0;
- unsigned n = 0;
- unsigned op = 0;
- unsigned bad = 0;
-
- if (memcmp(good_buf + offset, temp_buf, size) != 0) {
- prt("READ BAD DATA: offset = 0x%x, size = 0x%x\n",
- offset, size);
- prt("OFFSET\tGOOD\tBAD\tRANGE\n");
- while (size > 0) {
- c = good_buf[offset];
- t = temp_buf[i];
- if (c != t) {
- if (n == 0) {
- bad = short_at(&temp_buf[i]);
- prt("0x%5x\t0x%04x\t0x%04x", offset,
- short_at(&good_buf[offset]), bad);
- op = temp_buf[offset & 1 ? i+1 : i];
- }
- n++;
- badoff = offset;
- }
- offset++;
- i++;
- size--;
- }
- if (n) {
- prt("\t0x%5x\n", n);
- if (bad)
- prt("operation# (mod 256) for the bad data
-may be %u\n", ((unsigned)op & 0xff));
- else
- prt("operation# (mod 256) for the bad data
-unknown, check HOLE and EXTEND ops\n");
- } else
- prt("????????????????\n");
- report_failure(110);
- }
-}
-
-
-void
-check_size(void)
-{
- struct stat statbuf;
- off_t size_by_seek;
-
- if (fstat(fd, &statbuf)) {
- prterr("check_size: fstat");
- statbuf.st_size = -1;
- }
- size_by_seek = lseek(fd, (off_t)0, SEEK_END);
- if (file_size != statbuf.st_size || file_size != size_by_seek) {
- prt("Size error: expected 0x%llx stat 0x%llx seek 0x%llx\n",
- (unsigned long long)file_size,
- (unsigned long long)statbuf.st_size,
- (unsigned long long)size_by_seek);
- report_failure(120);
- }
-}
-
-
-void
-check_trunc_hack(void)
-{
- struct stat statbuf;
-
- ftruncate(fd, (off_t)0);
- ftruncate(fd, (off_t)100000);
- fstat(fd, &statbuf);
- if (statbuf.st_size != (off_t)100000) {
- prt("no extend on truncate! not posix!\n");
- exit(130);
- }
- ftruncate(fd, 0);
-}
-
-
-void
-doread(unsigned offset, unsigned size)
-{
- struct timeval t;
- off_t ret;
- unsigned iret;
-
- offset -= offset % readbdy;
- gettimeofday(&t, NULL);
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size read\n");
- log4(OP_SKIPPED, OP_READ, offset, size, &t);
- return;
- }
- if (size + offset > file_size) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping seek/read past end of file\n");
- log4(OP_SKIPPED, OP_READ, offset, size, &t);
- return;
- }
-
- log4(OP_READ, offset, size, 0, &t);
-
- if (testcalls <= simulatedopcount)
- return;
-
- if (!quiet && ((progressinterval &&
- testcalls % progressinterval == 0) ||
- (debug &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))))
- prt("%lu %lu.%lu read\t0x%x thru\t0x%x\t(0x%x bytes)\n",
- testcalls, t.tv_sec, t.tv_usec, offset, offset + size - 1,
- size);
- ret = lseek(fd, (off_t)offset, SEEK_SET);
- if (ret == (off_t)-1) {
- prterr("doread: lseek");
- report_failure(140);
- }
- iret = read(fd, temp_buf, size);
- if (iret != size) {
- if (iret == -1)
- prterr("doread: read");
- else
- prt("short read: 0x%x bytes instead of 0x%x\n",
- iret, size);
- report_failure(141);
- }
- check_buffers(offset, size);
-}
-
-
-void
-domapread(unsigned offset, unsigned size)
-{
- struct timeval t;
- unsigned pg_offset;
- unsigned map_size;
- char *p;
-
- offset -= offset % readbdy;
- gettimeofday(&t, NULL);
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size read\n");
- log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t);
- return;
- }
- if (size + offset > file_size) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping seek/read past end of file\n");
- log4(OP_SKIPPED, OP_MAPREAD, offset, size, &t);
- return;
- }
-
- log4(OP_MAPREAD, offset, size, 0, &t);
-
- if (testcalls <= simulatedopcount)
- return;
-
- if (!quiet && ((progressinterval &&
- testcalls % progressinterval == 0) ||
- (debug &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))))
- prt("%lu %lu.%lu mapread\t0x%x thru\t0x%x\t(0x%x bytes)\n",
- testcalls, t.tv_sec, t.tv_usec, offset, offset + size - 1,
- size);
-
- pg_offset = offset & page_mask;
- map_size = pg_offset + size;
-
- if ((p = (char *)mmap(0, map_size, PROT_READ, MAP_FILE | MAP_SHARED, fd,
- (off_t)(offset - pg_offset))) == (char *)-1) {
- prterr("domapread: mmap");
- report_failure(190);
- }
- memcpy(temp_buf, p + pg_offset, size);
- if (munmap(p, map_size) != 0) {
- prterr("domapread: munmap");
- report_failure(191);
- }
-
- check_buffers(offset, size);
-}
-
-
-void
-gendata(char *original_buf, char *good_buf, unsigned offset, unsigned size)
-{
- while (size--) {
- good_buf[offset] = testcalls % 256;
- if (offset % 2)
- good_buf[offset] += original_buf[offset];
- offset++;
- }
-}
-
-
-void
-dowrite(unsigned offset, unsigned size)
-{
- struct timeval t;
- off_t ret;
- unsigned iret;
-
- offset -= offset % writebdy;
- gettimeofday(&t, NULL);
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size write\n");
- log4(OP_SKIPPED, OP_WRITE, offset, size, &t);
- return;
- }
-
- log4(OP_WRITE, offset, size, file_size, &t);
-
- gendata(original_buf, good_buf, offset, size);
- if (file_size < offset + size) {
- if (file_size < offset)
- memset(good_buf + file_size, '\0', offset - file_size);
- file_size = offset + size;
- if (lite) {
- warn("Lite file size bug in fsx!");
- report_failure(149);
- }
- }
-
- if (testcalls <= simulatedopcount)
- return;
-
- if (!quiet && ((progressinterval &&
- testcalls % progressinterval == 0) ||
- (debug &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))))
- prt("%lu %lu.%lu write\t0x%x thru\t0x%x\t(0x%x bytes)\n",
- testcalls, t.tv_sec, t.tv_usec, offset, offset + size - 1,
- size);
- ret = lseek(fd, (off_t)offset, SEEK_SET);
- if (ret == (off_t)-1) {
- prterr("dowrite: lseek");
- report_failure(150);
- }
- iret = write(fd, good_buf + offset, size);
- if (iret != size) {
- if (iret == -1)
- prterr("dowrite: write");
- else
- prt("short write: 0x%x bytes instead of 0x%x\n",
- iret, size);
- report_failure(151);
- }
-}
-
-
-void
-domapwrite(unsigned offset, unsigned size)
-{
- struct timeval t;
- unsigned pg_offset;
- unsigned map_size;
- off_t cur_filesize;
- char *p;
-
- offset -= offset % writebdy;
- gettimeofday(&t, NULL);
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size write\n");
- log4(OP_SKIPPED, OP_MAPWRITE, offset, size, &t);
- return;
- }
- cur_filesize = file_size;
-
- log4(OP_MAPWRITE, offset, size, 0, &t);
-
- gendata(original_buf, good_buf, offset, size);
- if (file_size < offset + size) {
- if (file_size < offset)
- memset(good_buf + file_size, '\0', offset - file_size);
- file_size = offset + size;
- if (lite) {
- warn("Lite file size bug in fsx!");
- report_failure(200);
- }
- }
-
- if (testcalls <= simulatedopcount)
- return;
-
- if (!quiet && ((progressinterval &&
- testcalls % progressinterval == 0) ||
- (debug &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))))
- prt("%lu %lu.%lu mapwrite\t0x%x thru\t0x%x\t(0x%x bytes)\n",
- testcalls, t.tv_sec, t.tv_usec, offset, offset + size - 1,
- size);
-
- if (file_size > cur_filesize) {
- if (ftruncate(fd, file_size) == -1) {
- prterr("domapwrite: ftruncate");
- exit(201);
- }
- }
- pg_offset = offset & page_mask;
- map_size = pg_offset + size;
-
- if ((p = (char *)mmap(0, map_size, PROT_READ | PROT_WRITE,
- MAP_FILE | MAP_SHARED, fd,
- (off_t)(offset - pg_offset))) == (char *)-1) {
- prterr("domapwrite: mmap");
- report_failure(202);
- }
- memcpy(p + pg_offset, good_buf + offset, size);
- if (msync(p, map_size, 0) != 0) {
- prterr("domapwrite: msync");
- report_failure(203);
- }
- if (munmap(p, map_size) != 0) {
- prterr("domapwrite: munmap");
- report_failure(204);
- }
-}
-
-
-void
-dotruncate(unsigned size)
-{
- struct timeval t;
- int oldsize = file_size;
-
- size -= size % truncbdy;
- gettimeofday(&t, NULL);
- if (size > biggest) {
- biggest = size;
- if (!quiet && testcalls > simulatedopcount)
- prt("truncating to largest ever: 0x%x\n", size);
- }
-
- log4(OP_TRUNCATE, size, (unsigned)file_size, 0, &t);
-
- if (size > file_size)
- memset(good_buf + file_size, '\0', size - file_size);
- file_size = size;
-
- if (testcalls <= simulatedopcount)
- return;
-
- if ((progressinterval && testcalls % progressinterval == 0) ||
- (debug && (monitorstart == -1 || monitorend == -1 ||
- size <= monitorend)))
- prt("%lu %lu.%lu trunc\tfrom 0x%x to 0x%x\n",
- testcalls, t.tv_sec, t.tv_usec, oldsize, size);
- if (ftruncate(fd, (off_t)size) == -1) {
- prt("ftruncate1: %x\n", size);
- prterr("dotruncate: ftruncate");
- report_failure(160);
- }
-}
-
-
-void
-writefileimage()
-{
- ssize_t iret;
-
- if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
- prterr("writefileimage: lseek");
- report_failure(171);
- }
- iret = write(fd, good_buf, file_size);
- if ((off_t)iret != file_size) {
- if (iret == -1)
- prterr("writefileimage: write");
- else
- prt("short write: 0x%x bytes instead of 0x%llx\n",
- iret, (unsigned long long)file_size);
- report_failure(172);
- }
- if (lite ? 0 : ftruncate(fd, file_size) == -1) {
- prt("ftruncate2: %llx\n", (unsigned long long)file_size);
- prterr("writefileimage: ftruncate");
- report_failure(173);
- }
-}
-
-
-void
-docloseopen(void)
-{
- struct timeval t;
-
- if (testcalls <= simulatedopcount)
- return;
-
- log4(OP_CLOSEOPEN, file_size, (unsigned)file_size, 0, &t);
-
- gettimeofday(&t, NULL);
- if (debug)
- prt("%lu %lu.%lu close/open\n", testcalls, t.tv_sec, t.tv_usec);
- if (close(fd)) {
- prterr("docloseopen: close");
- report_failure(180);
- }
- fd = open(fname, O_RDWR, 0);
- if (fd < 0) {
- prterr("docloseopen: open");
- report_failure(181);
- }
-}
-
-
-void
-test(void)
-{
- unsigned long offset;
- unsigned long size = maxoplen;
- unsigned long rv = random();
- unsigned long op = rv % (3 + !lite + mapped_writes);
-
- /* turn off the map read if necessary */
-
- if (op == 2 && !mapped_reads)
- op = 0;
-
- if (simulatedopcount > 0 && testcalls == simulatedopcount)
- writefileimage();
-
- testcalls++;
-
- if (closeprob)
- closeopen = (rv >> 3) < (1 << 28) / closeprob;
-
- if (debugstart > 0 && testcalls >= debugstart)
- debug = 1;
-
- if (!quiet && testcalls < simulatedopcount && testcalls % 100000 == 0)
- prt("%lu...\n", testcalls);
-
- /*
- * READ: op = 0
- * WRITE: op = 1
- * MAPREAD: op = 2
- * TRUNCATE: op = 3
- * MAPWRITE: op = 3 or 4
- */
- if (lite ? 0 : op == 3 && (style & 1) == 0) /* vanilla truncate? */
- dotruncate(random() % maxfilelen);
- else {
- if (randomoplen)
- size = random() % (maxoplen+1);
- if (lite ? 0 : op == 3)
- dotruncate(size);
- else {
- offset = random();
- if (op == 1 || op == (lite ? 3 : 4)) {
- offset %= maxfilelen;
- if (offset + size > maxfilelen)
- size = maxfilelen - offset;
- if (op != 1)
- domapwrite(offset, size);
- else
- dowrite(offset, size);
- } else {
- if (file_size)
- offset %= file_size;
- else
- offset = 0;
- if (offset + size > file_size)
- size = file_size - offset;
- if (op != 0)
- domapread(offset, size);
- else
- doread(offset, size);
- }
- }
- }
- if (sizechecks && testcalls > simulatedopcount)
- check_size();
- if (closeopen)
- docloseopen();
-}
-
-
-void
-cleanup(sig)
- int sig;
-{
- if (sig)
- prt("signal %d\n", sig);
- prt("testcalls = %lu\n", testcalls);
- exit(sig);
-}
-
-
-void
-usage(void)
-{
- fprintf(stdout, "usage: %s",
- "fsx [-dnqLOW] [-b opnum] [-c Prob] [-l flen] [-m
-start:end] [-o oplen] [-p progressinterval] [-r readbdy] [-s style] [-t
-truncbdy] [-w writebdy] [-D startingop] [-N numops] [-P dirpath] [-S seed]
-fname\n\
- -b opnum: beginning operation number (default 1)\n\
- -c P: 1 in P chance of file close+open at each op (default infinity)\n\
- -d: debug output for all operations\n\
- -l flen: the upper bound on file size (default 262144)\n\
- -m startop:endop: monitor (print debug output) specified byte range
-(default 0:infinity)\n\
- -n: no verifications of file size\n\
- -o oplen: the upper bound on operation size (default 65536)\n\
- -p progressinterval: debug output at specified operation interval\n\
- -q: quieter operation\n\
- -r readbdy: 4096 would make reads page aligned (default 1)\n\
- -s style: 1 gives smaller truncates (default 0)\n\
- -t truncbdy: 4096 would make truncates page aligned (default 1)\n\
- -w writebdy: 4096 would make writes page aligned (default 1)\n\
- -D startingop: debug output starting at specified operation\n\
- -L: fsxLite - no file creations & no file size changes\n\
- -N numops: total # operations to do (default infinity)\n\
- -O: use oplen (see -o flag) for every op (default random)\n\
- -P: save .fsxlog and .fsxgood files in dirpath (default ./)\n\
- -S seed: for random # generator (default 1) 0 gets timestamp\n\
- -W: mapped write operations DISabled\n\
- -R: read() system calls only (mapped reads disabled)\n\
- fname: this filename is REQUIRED (no default)\n");
- exit(90);
-}
-
-
-int
-getnum(char *s, char **e)
-{
- int ret = -1;
-
- *e = (char *) 0;
- ret = strtol(s, e, 0);
- if (*e)
- switch (**e) {
- case 'b':
- case 'B':
- ret *= 512;
- *e = *e + 1;
- break;
- case 'k':
- case 'K':
- ret *= 1024;
- *e = *e + 1;
- break;
- case 'm':
- case 'M':
- ret *= 1024*1024;
- *e = *e + 1;
- break;
- case 'w':
- case 'W':
- ret *= 4;
- *e = *e + 1;
- break;
- }
- return (ret);
-}
-
-
-static const char *basename(const char *path)
-{
- char *c = strrchr(path, '/');
-
- return c ? c++ : path;
-}
-
-int
-main(int argc, char **argv)
-{
- int i, style, ch;
- char *endp;
- int dirpath = 0;
-
- goodfile[0] = 0;
- logfile[0] = 0;
-
- page_size = getpagesize();
- page_mask = page_size - 1;
-
- setvbuf(stdout, (char *)0, _IOLBF, 0); /* line buffered stdout */
-
- while ((ch = getopt(argc, argv, "b:c:dl:m:no:p:qr:s:t:w:D:LN:OP:RS:W"))
- != EOF)
- switch (ch) {
- case 'b':
- simulatedopcount = getnum(optarg, &endp);
- if (!quiet)
- fprintf(stdout, "Will begin at operation
-%ld\n",
- simulatedopcount);
- if (simulatedopcount == 0)
- usage();
- simulatedopcount -= 1;
- break;
- case 'c':
- closeprob = getnum(optarg, &endp);
- if (!quiet)
- fprintf(stdout,
- "Chance of close/open is 1 in %d\n",
- closeprob);
- if (closeprob <= 0)
- usage();
- break;
- case 'd':
- debug = 1;
- break;
- case 'l':
- maxfilelen = getnum(optarg, &endp);
- if (maxfilelen <= 0)
- usage();
- break;
- case 'm':
- monitorstart = getnum(optarg, &endp);
- if (monitorstart < 0)
- usage();
- if (!endp || *endp++ != ':')
- usage();
- monitorend = getnum(endp, &endp);
- if (monitorend < 0)
- usage();
- if (monitorend == 0)
- monitorend = -1; /* aka infinity */
- debug = 1;
- case 'n':
- sizechecks = 0;
- break;
- case 'o':
- maxoplen = getnum(optarg, &endp);
- if (maxoplen <= 0)
- usage();
- break;
- case 'p':
- progressinterval = getnum(optarg, &endp);
- if (progressinterval < 0)
- usage();
- break;
- case 'q':
- quiet = 1;
- break;
- case 'r':
- readbdy = getnum(optarg, &endp);
- if (readbdy <= 0)
- usage();
- break;
- case 's':
- style = getnum(optarg, &endp);
- if (style < 0 || style > 1)
- usage();
- break;
- case 't':
- truncbdy = getnum(optarg, &endp);
- if (truncbdy <= 0)
- usage();
- break;
- case 'w':
- writebdy = getnum(optarg, &endp);
- if (writebdy <= 0)
- usage();
- break;
- case 'D':
- debugstart = getnum(optarg, &endp);
- if (debugstart < 1)
- usage();
- break;
- case 'L':
- lite = 1;
- break;
- case 'N':
- numops = getnum(optarg, &endp);
- if (numops < 0)
- usage();
- break;
- case 'O':
- randomoplen = 0;
- break;
- case 'P':
- strncpy(goodfile, optarg, sizeof(goodfile));
- strcat(goodfile, "/");
- strncpy(logfile, optarg, sizeof(logfile));
- strcat(logfile, "/");
- dirpath = 1;
- break;
- case 'R':
- mapped_reads = 0;
- break;
- case 'S':
- seed = getnum(optarg, &endp);
- if (seed == 0)
- seed = time(0) % 10000;
- if (!quiet)
- fprintf(stdout, "Seed set to %d\n", seed);
- if (seed < 0)
- usage();
- break;
- case 'W':
- mapped_writes = 0;
- if (!quiet)
- fprintf(stdout, "mapped writes DISABLED\n");
- break;
-
- default:
- usage();
- /* NOTREACHED */
- }
- argc -= optind;
- argv += optind;
- if (argc != 1)
- usage();
- fname = argv[0];
-
- signal(SIGHUP, cleanup);
- signal(SIGINT, cleanup);
- signal(SIGPIPE, cleanup);
- signal(SIGALRM, cleanup);
- signal(SIGTERM, cleanup);
- signal(SIGXCPU, cleanup);
- signal(SIGXFSZ, cleanup);
- signal(SIGVTALRM, cleanup);
- signal(SIGUSR1, cleanup);
- signal(SIGUSR2, cleanup);
-
- initstate(seed, state, 256);
- setstate(state);
- fd = open(fname, O_RDWR|(lite ? 0 : O_CREAT|O_TRUNC), 0666);
- if (fd < 0) {
- prterr(fname);
- exit(91);
- }
- strncat(goodfile, dirpath ? basename(fname) : fname, 256);
- strcat (goodfile, ".fsxgood");
- fsxgoodfd = open(goodfile, O_RDWR|O_CREAT|O_TRUNC, 0666);
- if (fsxgoodfd < 0) {
- prterr(goodfile);
- exit(92);
- }
- strncat(logfile, dirpath ? basename(fname) : fname, 256);
- strcat (logfile, ".fsxlog");
- fsxlogf = fopen(logfile, "w");
- if (fsxlogf == NULL) {
- prterr(logfile);
- exit(93);
- }
- if (lite) {
- off_t ret;
- file_size = maxfilelen = lseek(fd, (off_t)0, SEEK_END);
- if (file_size == (off_t)-1) {
- prterr(fname);
- warn("main: lseek eof");
- exit(94);
- }
- ret = lseek(fd, (off_t)0, SEEK_SET);
- if (ret == (off_t)-1) {
- prterr(fname);
- warn("main: lseek 0");
- exit(95);
- }
- }
- original_buf = (char *) malloc(maxfilelen);
- for (i = 0; i < maxfilelen; i++)
- original_buf[i] = random() % 256;
- good_buf = (char *) malloc(maxfilelen);
- memset(good_buf, '\0', maxfilelen);
- temp_buf = (char *) malloc(maxoplen);
- memset(temp_buf, '\0', maxoplen);
- if (lite) { /* zero entire existing file */
- ssize_t written;
-
- written = write(fd, good_buf, (size_t)maxfilelen);
- if (written != maxfilelen) {
- if (written == -1) {
- prterr(fname);
- warn("main: error on write");
- } else
- warn("main: short write, 0x%x bytes instead
-of 0x%x\n",
- (unsigned)written, maxfilelen);
- exit(98);
- }
- } else
- check_trunc_hack();
-
- while (numops == -1 || numops--)
- test();
-
- if (close(fd)) {
- prterr("close");
- report_failure(99);
- }
- prt("All operations completed A-OK!\n");
-
- exit(0);
- return 0;
-}
+++ /dev/null
-#!/bin/bash -x
-
-MTPT=/mnt/lustre
-
-remount() {
- umount $MTPT || exit -1
- debugctl clear
- mount -t lustre_lite -o osc=OSCDEV-UUID,mdc=MDCDEV-UUID none $MTPT
-}
-
-# Test mkdir
-mkdir $MTPT/dir
-mkdir $MTPT/dir2
-
-# Test mkdir on existing directory
-mkdir $MTPT/dir
-
-remount
-
-# Test mkdir on existing directory with no locks already held
-mkdir $MTPT/dir
-
-remount
-
-# Use mknod to create a file
-./mcreate $MTPT/file
-# ...on an existing file.
-./mcreate $MTPT/file
-
-remount
-
-# Use mknod to create a file with no locks already held
-./mcreate $MTPT/file
-
-remount
-
-ls -l $MTPT/file
-
-remount
-
-cat $MTPT/file
-./mcreate $MTPT/file2
-cat $MTPT/file2
-./mcreate $MTPT/file3
-
-remount
-
-./tchmod 777 $MTPT/file3
-
-remount
-
-./mcreate $MTPT/file4
-./tchmod 777 $MTPT/file4
-
-remount
-
-ls -l $MTPT/file4
-./tchmod 777 $MTPT/file4
-
-remount
-
-cat $MTPT/file4
-./tchmod 777 $MTPT/file4
-
-remount
-
-touch $MTPT/file5
-touch $MTPT/file6
-touch $MTPT/file5
-
-remount
-
-touch $MTPT/file5
-
-remount
-
-echo foo >> $MTPT/file
-cat $MTPT/file
-
-remount
-
-cat $MTPT/file
-
-echo foo >> $MTPT/iotest
-echo bar >> $MTPT/iotest
-cat $MTPT/iotest
-
-remount
-
-cat $MTPT/iotest
-echo baz >> $MTPT/iotest
-
-remount
-
-ls $MTPT
-
-remount
-
-mkdir $MTPT/new
-ls $MTPT
-
-remount
-
-ls $MTPT
-mkdir $MTPT/newer
-ls $MTPT
-
-remount
-
-cat $MTPT/iotest
-echo "Testing truncation..."
-echo foo > $MTPT/iotest
-echo bar >> $MTPT/iotest
-cat $MTPT/iotest
-echo "trucating to 4 bytes now..."
-./truncate $MTPT/iotest 4
-cat $MTPT/iotest
-
-remount
-
-ls $MTPT
-rmdir $MTPT/foo
+++ /dev/null
-#!/bin/bash
-
-SRCDIR="`dirname $0`"
-. $SRCDIR/common.sh
-
-setup_opts "$@"
-
-set -vx
-
-MTPT1=/mnt/lustre1
-MTPT2=/mnt/lustre2
-
-remount() {
- umount $MTPT1 || exit -1
- umount $MTPT2 || exit -1
- debugctl clear
- setup_mount || fail "cannot remount /mnt/lustre"
-}
-
-fail() {
- echo "unexpected failure"
- exit -1
-}
-
-[ "`mount | grep $MTPT1`" ] || . llsetup.sh "$@" || exit -1
-
-mkdir $MTPT1/dir1 || fail
-echo "Next mkdir should fail"
-mkdir $MTPT2/dir1 && fail
-mkdir $MTPT2/dir2 || fail
-echo "Next mkdirs should fail"
-mkdir $MTPT1/dir2 && fail
-
-remount
-
-echo "Next 2 mkdir should fail"
-mkdir $MTPT2/dir1 && fail
-mkdir $MTPT1/dir2 && fail
-
-./mcreate $MTPT2/file1
-echo "Next mcreate should fail"
-./mcreate $MTPT2/file1 && fail
-./mcreate $MTPT2/file2 || fail
-echo "Next mcreate should fail"
-./mcreate $MTPT1/file2 && fail
-
-remount
-
-echo "Next 2 mcreates should fail"
-./mcreate $MTPT2/file1 && fail
-./mcreate $MTPT1/file2 && fail
-
-rmdir $MTPT1/dir2 || fail
-echo "Next rmdir should fail"
-rmdir $MTPT2/dir2 && fail
-rmdir $MTPT2/dir1 || fail
-
-remount
-
-echo "Next rpmdir should fail"
-
-echo "File I/O: you should see increasing sequences of contiguous numbers"
-echo 1 >> $MTPT1/file1
-cat $MTPT2/file1
-echo 2 >> $MTPT2/file1
-cat $MTPT1/file1
-echo 3 >> $MTPT2/file1
-cat $MTPT1/file1
-echo 4 >> $MTPT1/file1
-cat $MTPT1/file1
+++ /dev/null
-#include <ldap.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-
-int main(int argc, char **argv)
-{
- LDAP *ld;
- int err;
-
- ld = ldap_init("localhost", 389);
- if (!ld) {
- fprintf(stderr, "ldap_init: %s\n", strerror(errno));
- exit(1);
- }
-
- err = ldap_bind_s(ld, "cn=Manager,dc=lustre,dc=cfs", "secret",
- LDAP_AUTH_SIMPLE);
- if (err) {
- fprintf(stderr, "ldap_bind: %s\n", ldap_err2string(err));
- exit(1);
- }
-
-
-
-
-}
+++ /dev/null
-#!/bin/sh
-# Config file for setting up the lock manager
-SETUP_LDLM=y
+++ /dev/null
-#!/usr/bin/perl -w
-
-use IO::Handle;
-
-STDOUT->autoflush(1);
-STDERR->autoflush(1);
-
-my ($line, $memory);
-my $debug_line = 0;
-
-while ($line = <>) {
- $debug_line++;
- my ($file, $func, $lno, $name, $size, $addr, $type);
- if ($line =~ m/^.*\((.*):(\d+):(.*)\(\) (\d+ \| )?\d+\+\d+\): [vk](.*) '(.*)': (\d+) at (.*) \(tot .*$/) {
- $file = $1;
- $lno = $2;
- $func = $3;
- $type = $5;
- $name = $6;
- $size = $7;
- $addr = $8;
- printf("%8s %6d bytes at %s called %s (%s:%s:%d)\n", $type, $size,
- $addr, $name, $file, $func, $lno);
- } else {
- next;
- }
-
- if ($type eq 'malloced') {
- $memory->{$addr}->{name} = $name;
- $memory->{$addr}->{size} = $size;
- $memory->{$addr}->{file} = $file;
- $memory->{$addr}->{func} = $func;
- $memory->{$addr}->{lno} = $lno;
- $memory->{$addr}->{debug_line} = $debug_line;
- } else {
- if (!defined($memory->{$addr})) {
- print STDERR "*** Free without malloc ($size bytes at $addr, $file:$func:$lno)\n";
- next;
- }
- my ($oldname, $oldsize, $oldfile, $oldfunc, $oldlno) = $memory->{$addr};
-
- if ($memory->{$addr}->{size} != $size) {
- print STDERR "*** Free different size ($memory->{$addr}->{size} alloced, $size freed).\n";
- print STDERR " malloc at $memory->{$addr}->{file}:$memory->{$addr}->{func}:$memory->{$addr}->{lno}, free at $file:$func:$lno\n";
- next;
- }
-
- delete $memory->{$addr};
- }
-}
-
-# Sort leak output by allocation time
-my @sorted = sort {
- return $memory->{$a}->{debug_line} <=> $memory->{$b}->{debug_line};
-} keys(%{$memory});
-
-my $key;
-foreach $key (@sorted) {
- my ($oldname, $oldsize, $oldfile, $oldfunc, $oldlno) = $memory->{$key};
- print STDERR "*** Leak: $memory->{$key}->{size} bytes allocated at $key ($memory->{$key}->{file}:$memory->{$key}->{func}:$memory->{$key}->{lno}, debug file line $memory->{$key}->{debug_line})\n";
-}
-
-print "Done.\n";
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`/"
-[ -f $SRCDIR/common.sh ] || SRCDIR="/lib/lustre"
-
-. $SRCDIR/common.sh
-
-setup_opts "$@"
-
-TIME=`date +'%s'`
-
-$DBGCTL debug_kernel /tmp/debug.1.$TIME
-cleanup_client
-$DBGCTL debug_kernel /tmp/debug.2.$TIME
-cleanup_server
-
-cleanup_ldlm
-cleanup_lustre
-cleanup_portals
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-export DEBUG_WAIT=yes
-. $SRCDIR/llsetup.sh $SRCDIR/net-local.cfg $SRCDIR/ldlm.cfg $SRCDIR/obdecho.cfg $SRCDIR/client-echo.cfg || exit 2
-
-cat <<EOF
-**********************************************
-To run tests, use $OBDCTL.
-$OBDCTL
-device `$OBDCTL name2dev OSCDEV`
-probe
-
-To test basic locking functionality:
-test_ldlm
-
-The regression stress test will start some
-number of threads, each locking and unlocking
-extents from a set of resources. To run it:
-ldlm_regress_start [numthreads [refheld [numres [numext]]]]
-numthreads is the number of threads to start.
- (default 1)
-refheld is the total number of resources to hold,
- between all the threads. Once this number
- is reached, every time a lock is granted
- or matched, the oldest reference is
- decremented.
- (default 10)
-numres is the number of resources to use
- (default 10)
-numext is the number of extents to divide
- each resource into
- (default 10)
-
-To stop the test:
-ldlm_regress_stop
-**********************************************
-EOF
+++ /dev/null
-#!/bin/sh
-
-config=echo.xml
-LCONF=${LCONF:-../utils/lconf}
-LMC=${LMC:-../utils/lmc}
-
-SERVER=localhost
-CLIENT=localhost
-
-# FIXME: make LMC not require MDS for obdecho LOV
-MDSDEV=$TMP/mds1
-MDSSIZE=10000
-
-STRIPE_BYTES=65536
-STRIPES_PER_OBJ=2 # 0 means stripe over all OSTs
-
-LOV=0
-while [ "$1" ]; do
- case $1 in
- --lov) LOV="1" ;;
- *) OPTS="$OPTS $1" ;;
- esac
- shift
-done
-
-# create nodes
-$LMC -o $config --node $SERVER --net $SERVER tcp || exit 1
-
-if (($LOV)); then
- $LMC -m $config --node $SERVER --mds mds1 $MDSDEV $MDSSIZE || exit 10
- $LMC -m $config --lov lov1 mds1 $STRIPE_BYTES $STRIPES_PER_OBJ 0 || exit 11
- $LMC -m $config --node $SERVER --lov lov1 --obdtype=obdecho --ost || exit 12
- $LMC -m $config --node $SERVER --lov lov1 --obdtype=obdecho --ost || exit 13
-
- $LMC -m $config --node $CLIENT --echo_client lov1 || exit 3
-else
- $LMC -m $config --node $SERVER --obdtype=obdecho --ost || exit 2
- # force the osc to be configured (this is normally done when it is mounted)
- $LMC -m $config --node $CLIENT --osc OSC_$SERVER || exit 3
- $LMC -m $config --node $CLIENT --echo_client OSC_${SERVER} || exit 3
-fi
-
-$LCONF --gdb $OPTS $config || exit 4
-
-cat <<EOF
-
-run getattr tests as:
-../utils/lctl --device '\$ECHO_$SERVER' test_getattr 1000000
-EOF
+++ /dev/null
-#!/bin/sh
-
-LCONF=../utils/lconf
-
-if [ -f echo.xml ]; then
- ${LCONF} --cleanup echo.xml
-else
- echo "no echo.xml found"
-fi
-
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-export DEBUG_WAIT=yes
-. $SRCDIR/llsetup.sh $SRCDIR/net-local.cfg $SRCDIR/client-mount.cfg $SRCDIR/mds.cfg $SRCDIR/obdext2.cfg || exit 2
-
-debug_client_on
-#debug_client_off
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`/"
-[ -f $SRCDIR/common.sh ] || SRCDIR="/lib/lustre"
-
-. $SRCDIR/common.sh
-
-setup_opts "$@"
-
-[ -c /dev/portals ] || mknod /dev/portals c 10 240
-do_insmod $PORTALS/linux/oslib/portals.o || exit -1
-case $NETWORK in
-elan) do_insmod $PORTALS/linux/rqswnal/kqswnal.o || exit -1
- ;;
-tcp) do_insmod $PORTALS/linux/socknal/ksocknal.o || exit -1
- ;;
-*) fail "$0: unknown NETWORK '$NETWORK'" ;;
-esac
-
-[ -c /dev/obd ] || mknod /dev/obd c 10 241
-
-do_insmod $LUSTRE/obdclass/obdclass.o || exit -1
-do_insmod $LUSTRE/ptlrpc/ptlrpc.o || exit -1
-do_insmod $LUSTRE/ldlm/ldlm.o || exit -1
-do_insmod $LUSTRE/extN/extN.o || \
- echo "info: can't load extN.o module, not fatal if using ext3"
-do_insmod $LUSTRE/mds/mds.o || exit -1
-do_insmod $LUSTRE/mds/mds_extN.o || \
- echo "info: can't load mds_extN.o module, needs extN.o"
-do_insmod $LUSTRE/obdecho/obdecho.o || exit -1
-do_insmod $LUSTRE/obdfilter/obdfilter.o || exit -1
-do_insmod $LUSTRE/ost/ost.o || exit -1
-do_insmod $LUSTRE/osc/osc.o || exit -1
-do_insmod $LUSTRE/mdc/mdc.o || exit -1
-do_insmod $LUSTRE/lov/lov.o || exit -1
-do_insmod $LUSTRE/llite/llite.o || exit -1
-echo "$R/tmp/lustre-log" > /proc/sys/portals/debug_path
-
-list_mods
-
-
+++ /dev/null
-#!/bin/sh
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-export DEBUG_WAIT=yes
-. $SRCDIR/llsetup.sh $SRCDIR/net-client.cfg $SRCDIR/ldlm.cfg $SRCDIR/client-mount.cfg || exit 2
-
-debug_client_on
-#debug_client_off
+++ /dev/null
-#!/bin/sh
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-export DEBUG_WAIT=yes
-. $SRCDIR/llsetup.sh $SRCDIR/net-server.cfg $SRCDIR/ldlm.cfg $SRCDIR/mds.cfg $SRCDIR/obdfilter.cfg || exit 2
-
-debug_client_on
-#debug_client_off
+++ /dev/null
-#!/bin/sh
-# suggested boilerplate for test script
-
-LCONF=${LCONF:-../utils/lconf}
-NAME=${NAME:-local}
-
-config=$NAME.xml
-mkconfig=./$NAME.sh
-
-if [ ! -f $config -o $mkconfig -nt $config ]; then
- sh $mkconfig $config || exit 1
-fi
-
-${LCONF} --reformat --gdb $config || exit 2
+++ /dev/null
-#!/bin/sh
-# suggested boilerplate for test script
-
-LCONF=${LCONF:-../utils/lconf}
-NAME=${NAME:-local2-hack}
-
-config=$NAME.xml
-
-${LCONF} --reformat --gdb $config || exit 2
-
-../utils/lctl <<EOF
-newdev
-attach osc OSC2_localhost OSC2_localhost_UUID
-setup OBD_localhost_UUID NET_localhost_tcp_UUID
-newdev
-attach mdc MDC2_mds1 MDC2_uuid
-setup mds1_UUID NET_localhost_tcp_UUID
-quit
-EOF
-
-mount -t lustre_lite -o osc=OSC2_localhost_UUID,mdc=MDC2_uuid none /mnt/lustre2
+++ /dev/null
-#!/bin/sh
-
-LCONF=${LCONF:-../utils/lconf}
-NAME=${NAME:-local}
-TMP=${TMP:-/tmp}
-
-config=$NAME.xml
-mkconfig=./$NAME.sh
-
-if [ ! -f $config ]; then
- sh $mkconfig $config || exit 1
-fi
-
-sync; sleep 2; sync
-${LCONF} --cleanup --dump $TMP/debug $config
-LEAK=`dmesg | grep -v " 0 bytes" | grep leaked`
-if [ "$LEAK" ]; then
- echo "$LEAK" 1>&2
- mv $TMP/debug $TMP/debug.`date +%s`
- #exit -1
-fi
-BUSY=`dmesg | grep -i destruct`
-if [ "$BUSY" ]; then
- echo "$BUSY" 1>&2
- #exit -2
-fi
+++ /dev/null
-#!/bin/sh
-
-umount /mnt/lustre2
-umount /mnt/lustre1
-../utils/lctl <<EOF
-name2dev OSC2_localhost
-cleanup
-detach
-name2dev MDC2_mds1
-cleanup
-detach
-quit
-EOF
-
-LCONF=${LCONF:-../utils/lconf}
-NAME=${NAME:-local}
-
-config=$NAME.xml
-mkconfig=./$NAME.sh
-
-if [ ! -f $config -o $mkconfig -nt $config ]; then
- sh $mkconfig $config || exit 1
-fi
-
-${LCONF} --cleanup --dump /tmp/debug $config
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-export DEBUG_WAIT=yes
-. $SRCDIR/llrsetup.sh $SRCDIR/net-local.cfg $SRCDIR/client-mount.cfg $SRCDIR/mds.cfg $SRCDIR/obdext2.cfg || exit 2
-
-debug_client_on
-#debug_client_off
+++ /dev/null
-#!/bin/sh
-
-LCONF=${LCONF:-../utils/lconf}
-NAME=${NAME:-local}
-
-config=$NAME.xml
-mkconfig=./$NAME.sh
-
-if [ ! -f $config -o $mkconfig -nt $config ]; then
- sh $mkconfig $config || exit 1
-fi
-
-${LCONF} --gdb $config || exit 2
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`/"
-[ -f $SRCDIR/common.sh ] || SRCDIR="/lib/lustre"
-
-. $SRCDIR/common.sh
-
-setup_opts "$@"
-
-setup_portals
-setup_lustre
-setup_ldlm
-
-setup_server old_fs
-setup_client
+++ /dev/null
-#!/bin/sh -vx
-
-SRCDIR="`dirname $0`/"
-[ -f $SRCDIR/common.sh ] || SRCDIR="/lib/lustre"
-
-. $SRCDIR/common.sh
-
-setup_opts "$@"
-
-setup_portals || exit $?
-setup_lustre || exit $?
-setup_ldlm || exit $?
-
-setup_server new_fs || exit $?
-setup_client || exit $?
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`/"
-[ -f $SRCDIR/common.sh ] || SRCDIR="/lib/lustre"
-
-. $SRCDIR/common.sh
-
-setup_opts "$@"
-
-setup_portals || exit $?
-setup_lustre || exit $?
+++ /dev/null
-#!/bin/bash
-
-config=${1:-local.xml}
-
-LMC=${LMC:-../utils/lmc}
-TMP=${TMP:-/tmp}
-
-MDSDEV=$TMP/mds1
-MDSSIZE=100000
-
-OSTDEV=$TMP/ost1
-OSTSIZE=400000
-
-kver=`uname -r | cut -d "." -f 1,2`
-
-case $kver in
- 2.4) FSTYPE="--fstype=extN" ;;
- 2.5) FSTYPE="--fstype=ext3" ;;
- *) echo "Kernel version $kver not supported"
- exit 1
- ;;
-esac
-
-
-# create nodes
-${LMC} -o $config --node localhost --net localhost tcp || exit 1
-
-# configure mds server
-${LMC} -m $config --format --node localhost $FSTYPE --mds mds1 $MDSDEV $MDSSIZE || exit 2
-
-# configure ost
-${LMC} -m $config --format --node localhost $FSTYPE --ost $OSTDEV $OSTSIZE || exit 3
-
-# create client config
-${LMC} -m $config --node localhost --mtpt /mnt/lustre mds1 OSC_localhost || exit 4
+++ /dev/null
-#!/bin/bash
-
-config=${1:-lov.xml}
-
-LMC=${LMC:-../utils/lmc}
-TMP=${TMP:-/tmp}
-
-MDSDEV=$TMP/mds1
-MDSSIZE=50000
-
-OSTDEV1=$TMP/ost1
-OSTDEV2=$TMP/ost2
-OSTDEV3=$TMP/ost3
-OSTSIZE=100000
-
-STRIPE_BYTES=65536
-STRIPES_PER_OBJ=2 # 0 means stripe over all OSTs
-
-# create nodes
-${LMC} -o $config --node localhost --net localhost tcp || exit 1
-
-# configure mds server
-${LMC} -m $config --format --node localhost --mds mds1 $MDSDEV $MDSSIZE || exit 10
-
-# configure ost
-${LMC} -m $config --lov lov1 mds1 $STRIPE_BYTES $STRIPES_PER_OBJ 0 || exit 20
-${LMC} -m $config --node localhost --lov lov1 --ost $OSTDEV1 $OSTSIZE || exit 21
-${LMC} -m $config --node localhost --lov lov1 --ost $OSTDEV2 $OSTSIZE || exit 22
-${LMC} -m $config --node localhost --lov lov1 --ost $OSTDEV3 $OSTSIZE || exit 23
-
-# create client config
-${LMC} -m $config --node localhost --mtpt /mnt/lustre mds1 lov1 || exit 30
+++ /dev/null
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <string.h>
-#include <errno.h>
-
-
-/****************** Custom includes ********************/
-#include <linux/lustre_lite.h>
-#include <linux/lustre_idl.h>
-
-
-/****************** Functions ******************/
-int write_file(char *name, struct lov_mds_md *striping, int bufsize,
- char *buf1, char *buf2);
-
-
-/************************ Main **********************/
-
-#define STRIPE_SIZE 128 * 1024
-
-int main(int argc, char *argv[])
-{
- struct lov_mds_md a_striping;
- long bufsize = sizeof(long) * STRIPE_SIZE;
- char *rbuf, *wbuf;
- int data, *dp;
- int result;
-
- rbuf = malloc(bufsize);
- wbuf = malloc(bufsize);
- if (!rbuf || !wbuf) {
- fprintf(stderr, "%s: unable to allocate buffers\n", argv[0]);
- return 1;
- }
-
- /* Initialize to an easily-verified pattern */
- for (data = 0, dp = (int *)wbuf; data < STRIPE_SIZE; data++, dp++)
- *dp = data;
-
- /* Init defaults on striping info */
- a_striping.lmm_magic = LOV_MAGIC;
- a_striping.lmm_stripe_size = STRIPE_SIZE;
- a_striping.lmm_stripe_pattern = 0;
-
- /* Write file for OST1 only */
- /* Start at OST 0, and use only 1 OST */
- a_striping.lmm_stripe_offset = 0;
- a_striping.lmm_stripe_count = 1;
-
- result = write_file("/mnt/lustre/ost1", &a_striping, bufsize,
- wbuf, rbuf);
-
- if (result < 0)
- goto out;
-
- /* Write file for OST2 only */
- /* Start at OST 1, and use only 1 OST */
- a_striping.lmm_stripe_offset = 1;
- a_striping.lmm_stripe_count = 1;
-
- result = write_file("/mnt/lustre/ost2", &a_striping, bufsize,
- wbuf, rbuf);
-
- if (result < 0)
- goto out;
-
- /* Write file across both OST1 and OST2 */
- /* Start at OST 0, and use only 2 OSTs */
- a_striping.lmm_stripe_offset = 0;
- a_striping.lmm_stripe_count = 2;
-
- result = write_file("/mnt/lustre/ost1and2", &a_striping, bufsize,
- wbuf, rbuf);
-
- if (result < 0)
- goto out;
-
-out:
- free(rbuf);
- free(wbuf);
- return result;
-}
-
-
-int write_file(char *name, struct lov_mds_md *striping, int bufsize,
- char *wbuf, char *rbuf)
-{
- int fd, result;
-
- printf("opening %s\n", name);
- fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644);
- if (fd < 0) {
- fprintf(stderr, "\nUnable to open '%s': %s\n",
- name, strerror(errno));
- return -errno;
- }
-
- printf("setting stripe data on %s\n", name);
- result = ioctl(fd, LL_IOC_LOV_SETSTRIPE, striping);
- if (result < 0) {
- fprintf(stderr, "\nError on ioctl for '%s' (%d): %s\n",
- name, fd, strerror(errno));
- close(fd);
- return -errno;
- }
-
- /* Write bogus data */
- printf("writing data to %s\n", name);
- result = write(fd, wbuf, bufsize);
- if (result < 0) {
- fprintf(stderr, "\nerror: writing data to '%s' (%d): %s\n",
- name, fd, strerror(errno));
- close(fd);
- return -errno;
- }
-
- if (result != bufsize) {
- fprintf(stderr, "\nerror: short write to '%s' (%d): %d != %d\n",
- name, fd, result, bufsize);
- close(fd);
- return -1;
- }
-
- /* Seek to beginning again */
- printf("seeking in %s\n", name);
- result = lseek(fd, 0, SEEK_SET);
- if (result < 0) {
- fprintf(stderr, "\nerror: seeking to beginning '%s' (%d): %s\n",
- name, fd, strerror(errno));
- close(fd);
- return -errno;
- }
-
- /* Read bogus data back */
- printf("reading data from %s\n", name);
- result = read(fd, rbuf, bufsize);
- if (result < 0) {
- fprintf(stderr, "\nerror: reading data from '%s' (%d): %s\n",
- name, fd, strerror(errno));
- close(fd);
- return -errno;
- }
-
- if (result != bufsize) {
- fprintf(stderr,"\nerror: short read from '%s' (%d): %d != %d\n",
- name, fd, result, bufsize);
- close(fd);
- return -1;
- }
-
- if (memcmp(wbuf, rbuf, bufsize)) {
- fprintf(stderr, "\nerror: comparing data in '%s' (%d): %s\n",
- name, fd, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
-
- return 0;
-}
+++ /dev/null
-#!/bin/sh
-
-### REMOVE THE FOLLOWING LINES IN ORDER TO TEST LUSTRE WITH THIS CONFIG ###
-echo "lustre: edit /etc/lustre/lustre.cfg to enable, exiting" 1>&2
-exit 1
-
-# Common configuration options
-# Config file for setting up a local OST and MDS server
-NETWORK=tcp
-LOCALHOST=`hostname`
-SERVER=$LOCALHOST
-OSTNODE=$LOCALHOST
-CLIENTS=*
-PORT=988
-
-# Set up the lock manager (required)
-SETUP_LDLM=y
-
-#case `echo $LOCALHOST | sed "s/\.[^|]*//"` in
-case $LOCALHOST in
-$SERVER)
- # Config for setting up a metadata server
- MDSFS=extN
- MDSDEV=/tmp/mds
- MDSSIZE=50000
- SETUP_MDS=y
- ;;
-esac
-
-case $LOCALHOST in
-$OSTNODE)
- # Config for setting up an object storage target with obdfilter
- OSTDEV=/tmp/ost
- OSTSIZE=200000
- OSTFS=extN
- OSTTYPE=obdfilter
- SETUP_OST=y
- ;;
-esac
-
-case $LOCALHOST in
-$CLIENTS)
- # Config for setting up a client filesystem mount
- SETUP_MDC=y
- SETUP_OSC=y
- OSCMT=/mnt/lustre
- SETUP_MOUNT=y
- ;;
-esac
+++ /dev/null
-#!/bin/bash
-
-config=${1:-echo-no-gw.xml}
-
-LMC="save_cmd"
-LMC_REAL="../../lustre/utils/lmc -m $config"
-
-# TCP/IP servers
-SERVER_START=0
-SERVER_CNT=62
-
-TCPBUF=1048576
-
-h2ip () {
- echo "${1}"
-}
-BATCH=/tmp/lmc-batch.$$
-save_cmd() {
- echo "$@" >> $BATCH
-}
-
-[ -f $config ] && rm $config
-
-# Client node
-${LMC} --node client --tcpbuf $TCPBUF --net '*' tcp || exit 1
-
-# this is crude, but effective
-let server_per_gw=($SERVER_CNT / $GW_CNT )
-let tot_server=$server_per_gw*$GW_CNT
-
-let server=$SERVER_START
-while (( $server < $SERVER_CNT + SERVER_START ));
-do
- echo "server: $server"
- OST=ba$server
- # server node
- ${LMC} --node $OST --tcpbuf $TCPBUF --net $OST tcp || exit 1
- # the device on the server
- ${LMC} --node $OST --obdtype=obdecho --ost || exit 3
- # osc on client
- ${LMC} --node client --osc OSC_$OST
- let server=$server+1
-done
-
-$LMC_REAL --batch $BATCH
-rm -f $BATCH
+++ /dev/null
-#!/bin/sh
-
-LMC=/usr/local/cfs/lustre/utils/lmc
-# LMC="echo lmc"
-CONFIG=mcr-mds-failover.xml
-LUSTRE_QUERY=/usr/local/cfs/lustre-failover/lustre-query
-GW_NODE=mcr21
-CLIENT_ELAN=`hostname | sed s/[^0-9]*//;`
-OST_BA=ba50
-OST_UUID=10400010-5dec-11c2-0b5f-00301700041a
-MDS_DEVICE=/dev/sda3
-MDS_SIZE=500000
-TCPBUF=1048576
-
-MDSNODES=`$LUSTRE_QUERY -h emcri -s id=mds -f`
-ACTIVEMDS=`$LUSTRE_QUERY -h emcri -s id=mds -a`
-
-echo "MDS nodes: $MDSNODES, active: $ACTIVEMDS"
-
-h2elan () {
- echo $1 | sed 's/[^0-9]*//g'
-}
-
-h2ip () {
- echo "${1}"
-}
-
-
-# create client node
-$LMC -o $CONFIG --node client --net '*' elan
-$LMC -m $CONFIG --router --node mcr21 --tcpbuf $TCPBUF --net `h2ip $GW_NODE` tcp
-$LMC -m $CONFIG --router --node mcr21 --net `h2elan $GW_NODE` elan
-$LMC -m $CONFIG --node $GW_NODE --route elan `h2elan $GW_NODE` $CLIENT_ELAN
-
-# create MDS node entries
-for mds in $MDSNODES; do
- elanaddr=`$LUSTRE_QUERY -h emcri -s id=$mds -e`
- $LMC -m $CONFIG --node $mds --net $elanaddr elan
- $LMC -m $CONFIG --node $mds --mds mds_$mds $MDS_DEVICE $MDS_SIZE
-done
-
-# create OST node entry
-$LMC -m $CONFIG --node $OST_BA --tcpbuf $TCPBUF --net $OST_BA tcp
-$LMC -m $CONFIG --node $OST_BA --obduuid $OST_UUID --ost bluearc
-$LMC -m $CONFIG --node $GW_NODE --route tcp `h2ip $GW_NODE` $OST_BA
-
-# mount
-$LMC -m $CONFIG --node client --mtpt /mnt/lustre mds_$ACTIVEMDS OSC_$OST_BA
+++ /dev/null
-#!/bin/bash
-
-BASE=`hostname | sed "s/[i0-9]*$//"`
-[ $BASE = "mcr" ] && OSTBASE=${OSTBASE:-ba} || OSTBASE=${OSTBASE:-ba-ost-}
-
-config=${1:-$BASE.xml}
-
-BATCH=/tmp/lmc-batch.$$
-save_cmd() {
- echo "$@" >> $BATCH
-}
-
-LMC="save_cmd"
-LMC_REAL="../../lustre/utils/lmc -m $config"
-
-# TCP/IP servers
-SERVER_START=0
-SERVER_CNT=64
-GW_START=0
-GW_CNT=32
-MDS=${BASE}23
-UUIDLIST=${UUIDLIST:-/usr/local/admin/ba-ost/UUID.txt}
-
-echo "MDS: $MDS"
-
-# This is needed for to create route for elan network
-CLIENT_LO=36
-CLIENT_HI=155
-
-TCPBUF=1048576
-
-h2elan () {
- echo $1 | sed 's/[^0-9]*//g'
-}
-
-h2ip () {
- echo "${1}"
-}
-
-# map gateway NN to host NN (assumes mcr[22-25] are not gateways)
-gw2node() {
- [ $1 -gt 21 ] && echo $(($1 + 4)) || echo $1
-}
-
-[ -f $config ] && rm $config
-
-${LMC} --node $MDS --net `h2elan $MDS` elan || exit 1
-${LMC} --node $MDS --mds mds1 /tmp/mds1 100000 || exit 1
-${LMC} --lov lov1 mds1 65536 1 0
-
-# Client node
-#${LMC} --node client --tcpbuf $TCPBUF --net '*' tcp || exit 1
-${LMC} --node client --net '*' elan || exit 1
-${LMC} --node client --mtpt /mnt/lustre mds1 lov1
-
-# this is crude, but effective
-let server_per_gw=($SERVER_CNT / $GW_CNT )
-let tot_server=$server_per_gw*$GW_CNT
-echo "Allocating $server_per_gw OSTs per gateway."
-echo "For a total of $tot_server Blue Arc OSTs"
-
-let gw=$GW_START
-let server=$SERVER_START
-while (( $gw < $GW_CNT + GW_START ));
-do
- gwnode=$BASE`gw2node $gw`
- echo "Router: $gwnode"
- ${LMC} --router --node $gwnode --tcpbuf $TCPBUF --net `h2ip $gwnode` tcp || exit 1
- ${LMC} --node $gwnode --net `h2elan $gwnode` elan|| exit 1
- ${LMC} --node $gwnode --route elan `h2elan $gwnode` `h2elan $CLIENT_LO` `h2elan $CLIENT_HI` || exit 2
-
- let i=0
- while (( $i < $server_per_gw ));
- do
- OST=${OSTBASE}$server
- echo "server: $OST"
- OBD_UUID=`awk "/$OST / { print \\$3 }" $UUIDLIST`
- [ "$OBD_UUID" ] && OBD_UUID="--obduuid=$OBD_UUID" || echo "$OST: no UUID"
- # server node
- ${LMC} --node $OST --tcpbuf $TCPBUF --net $OST tcp || exit 1
- # the device on the server
- ${LMC} --lov lov1 --node $OST $OBD_UUID --ost bluearc || exit 3
- # route to server
- ${LMC} --node $gwnode --route tcp `h2ip $gwnode` $OST || exit 2
- let server=$server+1
- let i=$i+1
- done
-
- let gw=$gw+1
-done
-
-$LMC_REAL --batch $BATCH
-rm -f $BATCH
+++ /dev/null
-#!/bin/bash
-
-config=${1:-mcr.xml}
-
-LMC="../utils/lmc -m $config"
-
-# TCP/IP servers
-SERVERS="ba-ost-1 ba-ost-2"
-ROUTER=dev5
-
-# Elan clients
-CLIENT_LO=dev2
-CLIENT_HI=dev25
-
-TCPBUF=1048576
-
-
-h2elan () {
- echo $1 | sed 's/[^0-9]*//g'
-}
-
-h2ip () {
- echo "${1}"
-}
-
-[ -f $config ] && rm $config
-
-# Client node
-${LMC} --node client --net '*' elan || exit 1
-# Router node
-${LMC} --router --node $ROUTER --tcpbuf $TCPBUF --net `h2ip $ROUTER` tcp || exit 1
-${LMC} --node $ROUTER --net `h2elan $ROUTER` elan|| exit 1
-${LMC} --node $ROUTER --route elan `h2elan $ROUTER` `h2elan $CLIENT_LO` `h2elan $CLIENT_HI` || exit 2
-
-for s in $SERVERS
- do
- # server node
- ${LMC} --node $s --tcpbuf $TCPBUF --net $s tcp || exit 1
- # route to server
- ${LMC} --node $ROUTER --route tcp `h2ip $ROUTER` $s || exit 2
- # the device on the server
- ${LMC} --node $s --obdtype=obdecho --ost || exit 3
- # attach to the device on the client (this would normally be a moun)
- ${LMC} --node client --osc OSC_$s || exit 4
-done
+++ /dev/null
-#!/bin/bash
-
-config=${1:-mcrlov.xml}
-
-LMC="../utils/lmc -m $config"
-
-# TCP/IP servers
-SERVERS="ba-ost-1 ba-ost-2"
-ROUTER=dev5
-MDS=dev7
-TMP=${TMP:-/tmp}
-
-# Elan clients
-CLIENT_LO=dev2
-CLIENT_HI=dev25
-
-TCPBUF=1048576
-
-
-h2elan () {
- echo $1 | sed 's/[^0-9]*//g'
-}
-
-h2ip () {
- echo "${1}"
-}
-
-[ -f $config ] && rm $config
-
-# Client node
-${LMC} --node client --net '*' elan || exit 1
-# Router node
-${LMC} --router --node $ROUTER --tcpbuf $TCPBUF --net `h2ip $ROUTER` tcp || exit 1
-${LMC} --node $ROUTER --net `h2elan $ROUTER` elan|| exit 1
-${LMC} --node $ROUTER --route elan `h2elan $ROUTER` `h2elan $CLIENT_LO` `h2elan $CLIENT_HI` || exit 2
-
-${LMC} --node $MDS --net `h2elan $MDS` elan || exit 1
-${LMC} --node $MDS --mds mds1 $TMP/mds1 100000 || exit 1
-${LMC} --lov lov1 mds1 65536 0 0
-
-${LMC} --node client --mtpt /mnt/lustre mds1 lov1
-
-for s in $SERVERS
- do
- # server node
- ${LMC} --node $s --tcpbuf $TCPBUF --net $s tcp || exit 1
- # route to server
- ${LMC} --node $ROUTER --route tcp `h2ip $ROUTER` $s || exit 2
- # the device on the server
- ${LMC} --format --lov lov1 --node $s --ost bluearc || exit 3
-done
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`"
-. $SRCDIR/common.sh
-
-NETWORK=tcp
-LOCALHOST=localhost
-SERVER=localhost
-PORT=988
-TMP=${TMP:-/tmp}
-
-setup_portals
-setup_lustre
-
-MDSFS=ext2
-new_fs ${MDSFS} $TMP/mds 1000
-MDS=$LOOPDEV
-
-echo 0xffffffff > /proc/sys/portals/debug
-
-$OBDCTL <<EOF
-device 0
-attach mds MDSDEV
-setup ${MDS} ${MDSFS}
-quit
-EOF
-
-mknod /dev/request c 10 244
-
-./testreq --getattr
-./testreq --setattr
-./testreq --readpage
-./testreq --open
-./testreq --close junk_file_handle
-./testreq --create
-
-echo "Done."
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-rmmod llite
-rmmod mdc
-
-$OBDCTL <<EOF
-device 0
-cleanup
-detach
-quit
-EOF
-
-rmmod mds
-rmmod osc
-rmmod ost
-rmmod obdext2
-rmmod obdclass
-rmmod ptlrpc
-
-$PTLCTL <<EOF
-setup tcp
-disconnect localhost
-del_uuid self
-del_uuid mds
-EOF
-
-losetup -d ${LOOP}0
-
-killall acceptor
-rmmod ksocknal
-rmmod portals
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a metadata server
-MDSFS=extN
-MDSDEV=/tmp/mds
-MDSSIZE=25000
-SETUP_MDS=y
-# LOVUUID=LovUUID
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-int main(int argc, char ** argv)
-{
- int i, rc, count;
- char dirname[4096];
-
- if (argc < 3) {
- printf("Usage %s dirnamebase count\n", argv[0]);
- return 1;
- }
-
- if (strlen(argv[1]) > 4080) {
- printf("name too long\n");
- return 1;
- }
-
- count = strtoul(argv[2], NULL, 0);
-
- for (i=0 ; i < count ; i++) {
- sprintf(dirname, "%s-%d", argv[1], i);
- rc = mkdir(dirname, S_IFREG| 0444);
- if (rc) {
- printf("mkdir(%s) error: %s\n",
- dirname, strerror(errno));
- break;
- }
- if ((i % 10000) == 0)
- printf(" - created %d (time %ld)\n", i, time(0));
- }
- return rc;
-}
+++ /dev/null
-#!/bin/sh
-# Config file for running tests on a single host over loopback TCP
-NETWORK=tcp
+++ /dev/null
-#!/bin/bash
-
-config=${1:-mount2.xml}
-
-LMC=${LMC:-../utils/lmc}
-TMP=${TMP:-/tmp}
-
-MDSDEV=$TMP/mds1
-MDSSIZE=50000
-
-OSTDEV=$TMP/ost1
-OSTSIZE=100000
-
-kver=`uname -r | cut -d "." -f 1,2`
-
-case $kver in
- 2.4) FSTYPE="--fstype=extN" ;;
- 2.5) FSTYPE="--fstype=ext3" ;;
- *) echo "Kernel version $kver not supported"
- exit 1
- ;;
-esac
-
-# create nodes
-${LMC} -o $config --node localhost --net localhost tcp || exit 1
-
-# configure mds server
-${LMC} -m $config --format --node localhost $FSTYPE --mds mds1 $MDSDEV $MDSSIZE || exit 2
-
-# configure ost
-${LMC} -m $config --format --node localhost $FSTYPE --ost $OSTDEV $OSTSIZE || exit 3
-
-# create client config
-${LMC} -m $config --node localhost --mtpt /mnt/lustre1 mds1 OSC_localhost || exit 4
-${LMC} -m $config --node localhost --mtpt /mnt/lustre2 mds1 OSC_localhost || exit 4
+++ /dev/null
-#!/bin/bash
-#
-# Test case for 2 different filesystems mounted on the same client.
-# Uses 3 umls
-
-config=${1-mds-bug.xml}
-LMC=${LMC-../utils/lmc}
-TMP=${TMP:-/tmp}
-
-MDSDEV=$TMP/mds1
-MDSDEV2=$TMP/mds2
-MDSSIZE=50000
-
-OSTDEV1=$TMP/ost1
-OSTDEV2=$TMP/ost2
-OSTSIZE=100000
-
-MDSNODE=uml1
-OSTNODE=uml2
-CLIENT=uml3
-
-# create nodes
-${LMC} -o $config --node $MDSNODE --net $MDSNODE tcp || exit 1
-${LMC} -m $config --node $OSTNODE --net $OSTNODE tcp || exit 2
-${LMC} -m $config --node $CLIENT --net $CLIENT tcp || exit 3
-
-# configure mds server
-${LMC} -m $config --format --node $MDSNODE --mds mds1 $MDSDEV $MDSSIZE ||exit 10
-${LMC} -m $config --format --node $MDSNODE --mds mds2 $MDSDEV2 $MDSSIZE ||exit 10
-
-# configure ost
-${LMC} -m $config --lov lov1 mds1 65536 0 0 || exit 20
-${LMC} -m $config --lov lov2 mds2 65536 0 0 || exit 20
-${LMC} -m $config --node $OSTNODE --lov lov1 --ost $OSTDEV1 $OSTSIZE || exit 21
-${LMC} -m $config --node $OSTNODE --lov lov2 --ost $OSTDEV2 $OSTSIZE || exit 22
-
-# create client config
-${LMC} -m $config --node $CLIENT --mtpt /mnt/lustre mds1 lov1 || exit 30
-${LMC} -m $config --node $CLIENT --mtpt /mnt/lustre2 mds2 lov2 || exit 30
-
-
-
-
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-int main(int argc, char ** argv)
-{
- int rc;
-
- if (argc < 2) {
- printf("Usage %s filename\n", argv[0]);
- return 1;
- }
-
- rc = unlink(argv[1]);
- if (rc) {
- printf("unlink(%s) error: %s\n", argv[1], strerror(errno));
- }
- return rc;
-}
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a remote server with a real OST
-NETWORK=tcp
-LOCALHOST=dev5
-SERVER=dev4
-PORT=988
+++ /dev/null
-#!/bin/sh
-# Config file for running tests on a single host over loopback TCP
-NETWORK=tcp
-LOCALHOST=localhost
-SERVER=localhost
-PORT=988
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a remote server with a real OST
-NETWORK=tcp
-LOCALHOST=dev4
-SERVER=dev4
-PORT=988
+++ /dev/null
-#!/bin/sh
-# Config file for setting up an object storage target with obdfilter
-OSTDEV=/dev/hda7
-OSTFS=ext2
-OSTTYPE=obdfilter
-SETUP_OST=y
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a test (echo) OST
-OSTTYPE=obdecho
-SETUP_OST=y
+++ /dev/null
-#!/bin/sh
-# Config file for setting up an object storage target with obdfilter
-OSTDEV=/tmp/ost
-OSTSIZE=10000
-OSTFS=extN
-OSTTYPE=obdfilter
-SETUP_OST=y
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/wait.h>
-#include <sys/ioctl.h>
-
-#include <linux/lustre_lite.h>
-
-#ifndef O_DIRECT
-# define O_DIRECT 040000 /* direct disk access hint */
-#endif
-
-int main(int argc, char *argv[])
-{
- char filename[1024];
- unsigned long count, i;
- int thread = 0;
- int threads = 0;
- int rc = 0;
- int fd, ioctl_flags = 0;
-
- if (argc < 3 || argc > 4) {
- fprintf(stderr, "usage: %s <filename> <iterations> [threads]\n",
- argv[0]);
- exit(1);
- }
-
- count = strtoul(argv[2], NULL, 0);
- if (argc == 4)
- threads = strtoul(argv[3], NULL, 0);
-
- for (i = 1; i <= threads; i++) {
- rc = fork();
- if (rc < 0) {
- fprintf(stderr, "error: %s: #%ld - %s\n", argv[0], i,
- strerror(rc = errno));
- break;
- } else if (rc == 0) {
- thread = i;
- argv[2] = "--device";
- break;
- } else
- printf("%s: thread #%ld (PID %d) started\n",
- argv[0], i, rc);
- rc = 0;
- }
-
- if (threads && thread == 0) { /* parent process */
- int live_threads = threads;
-
- while (live_threads > 0) {
- int status;
- pid_t ret;
-
- ret = waitpid(0, &status, 0);
- if (ret == 0) {
- continue;
- }
-
- if (ret < 0) {
- fprintf(stderr, "error: %s: wait - %s\n",
- argv[0], strerror(errno));
- if (!rc)
- rc = errno;
- } else {
- /*
- * This is a hack. We _should_ be able to use
- * WIFEXITED(status) to see if there was an
- * error, but it appears to be broken and it
- * always returns 1 (OK). See wait(2).
- */
- int err = WEXITSTATUS(status);
- if (err || WIFSIGNALED(status))
- fprintf(stderr,
- "%s: PID %d had rc=%d\n",
- argv[0], ret, err);
- if (!rc)
- rc = err;
-
- live_threads--;
- }
- }
- } else {
- if (threads)
- sprintf(filename, "%s-%d", argv[1], thread);
- else
- strcpy(filename, argv[1]);
-
- fd = open(filename, O_RDWR|O_CREAT, 0644);
- if (fd < 0) {
- fprintf(stderr, "open(%s, O_CREAT): %s\n", filename,
- strerror(errno));
- exit(errno);
- }
- if (close(fd) < 0) {
- fprintf(stderr, "close(): %s\n", strerror(errno));
- rc = errno;
- goto unlink;
- }
-
- for (i = 0; i < count; i++) {
- fd = open(filename, O_RDWR|O_LARGEFILE|O_DIRECT);
- if (fd < 0) {
- fprintf(stderr, "open(%s, O_RDWR): %s\n",
- filename, strerror(errno));
- rc = errno;
- break;
- }
- if (ioctl(fd, LL_IOC_SETFLAGS, &ioctl_flags) < 0) {
- fprintf(stderr, "ioctl(): %s\n",
- strerror(errno));
- rc = errno;
- break;
- }
- if (close(fd) < 0) {
- fprintf(stderr, "close(): %s\n",
- strerror(errno));
- rc = errno;
- break;
- }
- }
- unlink:
- if (unlink(filename) < 0) {
- fprintf(stderr, "unlink(%s): %s\n", filename,
- strerror(errno));
- rc = errno;
- }
- if (threads)
- printf("Thread %d done: rc = %d\n", thread, rc);
- else
- printf("Done: rc = %d\n", rc);
- }
- return rc;
-}
+++ /dev/null
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-int main(int argc, char **argv)
-{
- int fd;
-
- if (argc != 2) {
- printf("Usage openme <filename>\n");
- exit(1);
- }
-
- fd = open(argv[1], O_RDONLY | O_CREAT, 0600);
- if (fd == -1) {
- printf("Error opening %s\n", argv[1]);
- exit(1);
- }
-
- sleep(10000000);
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#define T1 "write before unlink\n"
-#define T2 "write after unlink\n"
-char buf[128];
-
-int main(int argc, char **argv)
-{
- int fd, rc;
-
- if (argc != 2) {
- fprintf(stderr, "usage: %s filename\n", argv[0]);
- exit(1);
- } else {
- fprintf(stderr, "congratulations - program starting\n");
- }
-
- fprintf(stderr, "opening\n");
- fd = open(argv[1], O_RDWR | O_TRUNC | O_CREAT, 0644);
- if (fd == -1) {
- fprintf(stderr, "open (normal) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "writing\n");
- rc = write(fd, T1, strlen(T1) + 1);
- if (rc != strlen(T1) + 1) {
- fprintf(stderr, "write (normal) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "closing\n");
- rc = close(fd);
- if (rc) {
- fprintf(stderr, "close (normal) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "opening again\n");
- fd = open(argv[1], O_RDWR);
- if (fd == -1) {
- fprintf(stderr, "open (unlink) %s\n", strerror(errno));
- exit(1);
- }
-
-#if 0
- fprintf(stderr, "unlinking\n");
- rc = unlink(argv[1]);
- if (rc) {
- fprintf(stderr, "unlink %s\n", strerror(errno));
- exit(1);
- }
-#else
- printf("unlink %s and press enter\n", argv[1]);
- getc(stdin);
-#endif
-
- fprintf(stderr, "reading\n");
- rc = read(fd, buf, strlen(T1) + 1);
- if (rc != strlen(T1) + 1) {
- fprintf(stderr, "read (unlink) %s rc %d\n",
- strerror(errno), rc);
- exit(1);
- }
-
- fprintf(stderr, "comparing data\n");
- if (memcmp(buf, T1, strlen(T1) + 1) ) {
- fprintf(stderr, "FAILURE: read wrong data after unlink\n");
- exit(1);
- }
-
- fprintf(stderr, "truncating\n");
- rc = ftruncate(fd, 0);
- if (rc ) {
- fprintf(stderr, "truncate (unlink) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "seeking\n");
- rc = lseek(fd, 0, SEEK_SET);
- if (rc) {
- fprintf(stderr, "seek (after unlink trunc) %s\n",
- strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "writing again\n");
- rc = write(fd, T2, strlen(T2) + 1);
- if (rc != strlen(T2) + 1) {
- fprintf(stderr, "write (after unlink trunc) %s (rc %d)\n",
- strerror(errno), rc);
- exit(1);
- }
-
- fprintf(stderr, "seeking\n");
- rc = lseek(fd, 0, SEEK_SET);
- if (rc) {
- fprintf(stderr, "seek (before unlink read) %s\n",
- strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "reading again\n");
- rc = read(fd, buf, strlen(T2) + 1);
- if (rc != strlen(T2) + 1) {
- fprintf(stderr, "read (after unlink rewrite) %s\n",
- strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "comparing data again\n");
- if (memcmp(buf, T2, strlen(T2) + 1)) {
- fprintf(stderr, "FAILURE: read wrong data after rewrite\n");
- exit(1);
- }
-
- fprintf(stderr, "closing again\n");
- rc = close(fd);
- if (rc) {
- fprintf(stderr, "close (unlink) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "SUCCESS - goto beer\n");
- return 0;
-}
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-SERVER=localhost
-PORT=988
-TMP=${TMP:-/tmp}
-
-$ACCEPTOR $PORT
-
-$PTLCTL <<EOF
-mynid localhost
-setup tcp
-connect $SERVER $PORT
-add_uuid $SERVER
-add_uuid self
-quit
-EOF
-
-setup_lustre
-
-tmp_fs ext2 $TMP/fs 10000
-OBD=${LOOPDEV}
-
-$OBDCTL <<EOF
-device 0
-attach obdext2 OBDEXT2DEV
-setup ${OBD}
-device 1
-attach ost OSTDEV
-setup 0
-device 2
-attach osc OSCDEV
-setup -1
-quit
-EOF
+++ /dev/null
-#!/bin/sh
-
-#[ -e /proc/sys/portals/debug ] && echo 0 > /proc/sys/portals/debug
-TGT=/mnt/lustre/client.txt
-SRC=/usr/lib/dbench/client.txt
-[ ! -e $TGT -a -e $SRC ] && echo "copying $SRC to $TGT" && cp $SRC $TGT
-SRC=/usr/lib/dbench/client_plain.txt
-[ ! -e $TGT -a -e $SRC ] && echo "copying $SRC to $TGT" && cp $SRC $TGT
-cd /mnt/lustre
-dbench -c client.txt $@
+++ /dev/null
-#!/bin/sh
-SRCDIR=.
-
-. common.sh
-
-reconnect () {
-
-$OBDCTL <<EOF
-name2dev RPCDEV
-newconn
-quit
-EOF
-
-}
-
-
-
-echo
-echo "Test 1 drop request:" `date` "creating /mnt/lustre/foo"
-echo
-rm -rf /mnt/lustre/*
-echo 0x80000107 > /proc/sys/lustre/fail_loc
-touch /mnt/lustre/foo &
-ps axww | grep touch
-echo "MDS dropped create request -- sleep 4 secs - watch for timeout"
-sleep 7
-# reconnect
-sleep 1
-echo "did things recover? check for file foo."
-ls -l /mnt/lustre
-echo "Test 1 done"
-
-
-echo
-echo "Test 2 test delay queue:" `date` "creating /mnt/lustre/foo"
-echo
-rm -rf /mnt/lustre/*
-mkdir /mnt/lustre/a
-echo 0x80000107 > /proc/sys/lustre/fail_loc
-touch /mnt/lustre/foo &
-ps axww | grep touch
-echo "MDS dropped create request -- sleep 4 secs - watch for timeout"
-sleep 4
-touch /mnt/lustre/a/f &
-#reconnect
-sleep 5
-echo "did things recover? check for file foo and a/f"
-ls -l /mnt/lustre
-ls -l /mnt/lustre/a
-echo "Test 2 done"
-
-echo
-echo "Test 3 dropped reply:" `date` "creating /mnt/lustre/foo2"
-echo
-rm -rf /mnt/lustre/*
-echo 0x80000119 > /proc/sys/lustre/fail_loc
-touch /mnt/lustre/foo2 &
-ps axww | grep touch
-echo "MDS dropped create request -- sleep 4 secs - watch for timeout"
-sleep 4
-# reconnect
-echo failure cleared
-sleep 4
-echo "did things recover? check for file foo2"
-ls -l /mnt/lustre
-echo "Test 3 done"
-
-
-echo
-echo "Test 4: Multiple failures"
-echo
-echo 0x0000107 > /proc/sys/lustre/fail_loc
-touch /mnt/lustre/bar &
-ps axww | grep touch
-echo "touch program will have repeated failures sleeping 10"
-sleep 10
-echo 0 > /proc/sys/lustre/fail_loc
-# reconnect
-sleep 6
-echo "failure cleared"
-echo "did things recover? Check for file bar"
-ls -l /mnt/lustre/bar
-
-echo "Test 4 done"
-
-
-echo
-echo "Test 5: Continue writing during recovery:" `date` "creating and writing/mnt/lustre/foo"
-echo
-rm -rf /mnt/lustre/*
-./openme /mnt/lustre/foo3 &
-./writeme /mnt/lustre/iogoeson &
-sleep 1
-ls -l /mnt/lustre
-echo 0x80000107 > /proc/sys/lustre/fail_loc
-mknod /mnt/lustre/dev c 10 240 &
-echo "MDS dropped create request -- sleep 4 secs - watch for timeout"
-sleep 6
-# reconnect
-sleep 1
-echo "did things recover? check for file foo, bar, check log for reopen."
-ls -l /mnt/lustre
-echo "Test 5 done"
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`"
-. $SRCDIR/common.sh
-
-. $SRCDIR/llmount.sh
-
-MNT="setup_mount"
-
-test_fail() {
- echo $1 > /proc/sys/lustre/fail_loc
- shift
- echo "Running '$*'"
- $*
-
- echo "Cleaning up and restarting MDS"
- umount /mnt/lustre || fail "unable to unmount"
- $OBDCTL <<- EOF
- name2dev MDSDEV
- cleanup
- detach
- quit
- EOF
-
- echo 0 > /proc/sys/lustre/fail_loc
-
- $OBDCTL <<- EOF
- newdev
- attach mds MDSDEV
- setup ${MDS} ${MDSFS}
- quit
- EOF
- $MNT
-}
-
-#set -vx
-
-touch /mnt/lustre/foo
-chmod a+x /mnt/lustre/foo
-sync
-
-# OBD_FAIL_MDS_REINT_SETATTR_WRITE - MDS will discard data from setattr
-test_fail 0x10a chmod 000 /mnt/lustre/foo
-ls -l /mnt/lustre/foo
-[ ! -x /mnt/lustre/foo ] && fail "/mnt/lustre/foo is not executable!"
-
-# OBD_FAIL_MDS_REINT_CREATE_WRITE - MDS will not create the file
-test_fail 0x10c touch /mnt/lustre/bar
-ls /mnt/lustre/bar
-[ $? -eq 0 ] && fail "/mnt/lustre/bar was created!"
-
-# OBD_FAIL_MDS_REINT_UNLINK_WRITE - MDS will discard data from unlink
-test_fail 0x10e rm /mnt/lustre/foo
-ls /mnt/lustre/foo
-[ $? -eq 1 ] && fail "/mnt/lustre/foo has been removed!"
-
-# OBD_FAIL_MDS_REINT_RENAME_WRITE - MDS will discard data from rename
-test_fail 0x112 mv /mnt/lustre/foo /mnt/lustre/bar
-ls /mnt/lustre/foo /mnt/lustre/bar
-[ ! -f /mnt/lustre/foo -o -f /mnt/lustre/bar ] && \
- fail "/mnt/lustre/foo has been renamed to bar!"
-
-echo "Done."
+++ /dev/null
-#!/bin/sh
-
-fail() {
- echo "ERROR: $1" 1>&2
- [ $2 ] && RC=$2 || RC=1
- exit $RC
-}
-
-test_fail() {
- oldtimeout=`cat /proc/sys/lustre/timeout`
- echo $TIMEOUT > /proc/sys/lustre/timeout
- echo $1 > /proc/sys/lustre/fail_loc
- shift
- $* &
- sleep $TIMEOUT
- sleep 2 # fudge
- kill -9 $!
-
- echo $oldtimeout > /proc/sys/lustre/timeout
- echo 0 > /proc/sys/lustre/fail_loc
- umount -f /mnt/lustre || fail "cannot unmount /mnt/lustre"
- mount -t lustre_lite -o "osc=$OSC,mdc=$MDC" none /mnt/lustre || \
- fail "cannot remount $OSC/$MDC on /mnt/lustre"
-}
-
-set -vx
-
-LCTL=../utils/lctl
-OSC=OSC_localhost_UUID
-MDC=MDC_client1_UUID
-TIMEOUT=5 # complete in finite time
-
-[ "`mount | grep /mnt/lustre`" ] || echo | sh llmount.sh || exit -1
-
-# GETATTR_NET - ls will hang on the getattr
-# test_fail 0x102 ls -l /mnt/lustre
-
-# READPAGE_NET - ls will hang reading in new pages (lost+found is not in cache)
-test_fail 0x104 ls /mnt/lustre
-
-sleep 1
-
-# REINT_NET - touch will hang on setattr
-test_fail 0x107 touch /mnt/lustre
-
-# REINT_NET - touch will hang on create
-test_fail 0x107 touch /mnt/lustre/tt
-
-# REINT_NET - mv will hang on rename
-touch /mnt/lustre/foo
-test_fail 0x107 mv /mnt/lustre/foo /mnt/lustre/bar
-
-# REINT_NET - rm will hang on unlink
-touch /mnt/lustre/salmon
-test_fail 0x107 rm /mnt/lustre/salmon
-
-# OPEN_NET - touch will hang on open
-touch /mnt/lustre/foo
-test_fail 0x113 cat /mnt/lustre/foo
-
-# CLOSE_NET - ls will hang on close
-test_fail 0x115 ./testreq --close junk_file_handle
-
-echo 0 > /proc/sys/lustre/fail_loc
-
-echo "Done."
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`"
-. $SRCDIR/common.sh
-
-setup_opts "$@"
-
-set -vx
-
-test_fail() {
- echo $1 > /proc/sys/lustre/fail_loc
- shift
- echo "Running '$*'"
- $* &
- sleep 1
- kill -9 $!
-
- echo 0 > /proc/sys/lustre/fail_loc
- umount /mnt/lustre || fail "cannot unmount /mnt/lustre"
- setup_mount || fail "cannot remount /mnt/lustre"
-}
-
-[ "`mount | grep /mnt/lustre`" ] || . llsetup.sh "$@" || exit -1
-
-# OBD_FAIL_OST_OPEN_NET: OST will discard open request packet
-touch /mnt/lustre/foo
-test_fail 0x208 cat /mnt/lustre/foo
-
-# OBD_FAIL_OST_CLOSE_NET: OST will discard close request packet
-test_fail 0x209 cat /mnt/lustre/foo
-
-# OBD_FAIL_OST_CREATE_NET: OST will discard create request packet
-test_fail 0x204 touch /mnt/lustre/bar
-
-# OBD_FAIL_OST_DESTROY_NET: OST will discard destroy request packet
-test_fail 0x205 rm /mnt/lustre/foo
-
-# OBD_FAIL_OST_BRW_NET: OST will discard read request packet
-echo foo >> /mnt/lustre/foo
-test_fail 0x20a cat /mnt/lustre/foo
-
-# OBD_FAIL_OST_BRW_NET: OST will discard write request packet
-test_fail 0x20a "echo bar >> /mnt/lustre/foo"
-
-# OBD_FAIL_OST_PUNCH_NET: OST will discard truncate request packet
-test_fail 0x208 "echo bar > /mnt/lustre/foo"
-
-# OBD_FAIL_OST_STATFS_NET: OST will discard statfs request packet
-test_fail 0x208 df /mnt/lustre
-
-echo "Done."
+++ /dev/null
-#!/bin/sh
-[ -z "$SIZE" ] && SIZE=5g
-[ -z "$LOOPS" ] && LOOPS=9999
-[ -z "$VERIFY" ] && VERIFY="-+d"
-[ -z "$ODIR" ] && ODIR="-I"
-[ -z "$REC" ] && REC=64
-[ -z "$FILE" ] && FILE=/mnt/lustre/test.$$
-[ $1 ] && SIZE=$1
-COUNT=0
-rm -f endiozone
-echo 0 > /proc/sys/portals/debug
-while date; do
- echo "Test #$COUNT"
- iozone $VERIFY $ODIR -r $REC -i 0 -i 1 -f $FILE -s $SIZE 2>&1 || exit $?
- COUNT=`expr $COUNT + 1`
- [ -f endiozone -o $COUNT -ge $LOOPS ] && rm -f endiozone && exit 0
-done | tee /tmp/iozone.log
+++ /dev/null
-#!/bin/sh
-export PATH=/sbin:/usr/sbin:$PATH
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-COUNT=${COUNT:-1000000}
-COUNT_10=`expr $COUNT / 10`
-COUNT_100=`expr $COUNT / 100`
-
-ENDRUN=endrun-`hostname`
-
-ECHONAME="`$OBDCTL device_list 2> /dev/null | awk '/ echo_client / { print $4 }' | tail -1`"
-
-if [ -z "$ECHONAME" ]; then
- echo "$0: needs an ECHO_CLIENT set up first" 1>&2
- exit 1
-fi
-
-cleanup () {
- $OBDCTL --device \$$ECHONAME destroy $OID
-}
-
-runthreads() {
- THR=$1
- DO=$2
- CNT=$3
- V=$4
- PGS=$5
-
- case $DO in
- test_getattr)
- RW=
- ;;
- test_brw_write)
- DO=test_brw
- RW=w
- ;;
- test_brw_read)
- DO=test_brw
- RW=r
- ;;
- esac
-
- $OBDCTL --threads $THR v \$$ECHONAME $DO $CNT $RW $V $PGS $OID || exit 1
-
- if [ -e $ENDRUN ]; then
- rm $ENDRUN
- echo "exiting because $ENDRUN file was found"
- cleanup
- fi
-}
-
-[ -z "$OID" ] && OID=`$OBDCTL --device \\$$ECHONAME create 1 | awk '/is object id/ { print $6 }'`
-[ -z "$OID" ] && echo "error creating object" 1>&2 && exit 1
-
-# TODO: obdctl needs to check on the progress of each forked thread
-# (IPC SHM, sockets?) to see if it hangs.
-while date; do
- PG=1
- PGVW=16
- PGVR=16
-
- # We use '--threads 1 X' instead of '--device X' so that
- # obdctl can monitor the forked thread for progress (TODO).
- debug_server_off
- debug_client_off
- runthreads 1 test_brw_write 1000 -30 $PG
- runthreads 1 test_brw_read 1000 -30 $PG
-
- [ "$PGVW" ] && runthreads 1 test_brw_write 100 -30 $PGVW
- [ "$PGVW" ] && runthreads 1 test_brw_read 1600 -30 $PG
- [ "$PGVR" ] && runthreads 1 test_brw_read 100 -30 $PGVR
-
- runthreads 1 test_brw_write $COUNT -30 $PG
- runthreads 1 test_brw_read $COUNT -30 $PG
-
- [ "$PGVW" ] && runthreads 1 test_brw_write $COUNT_10 -30 $PGVW
- [ "$PGVR" ] && runthreads 1 test_brw_read $COUNT_10 -30 $PGVR
-
- runthreads 2 test_brw_write $COUNT -30 $PG
- runthreads 2 test_brw_read $COUNT -30 $PG
-
- [ "$PGVW" ] && runthreads 2 test_brw_write $COUNT_10 -30 $PGVW
- [ "$PGVR" ] && runthreads 2 test_brw_read $COUNT_10 -30 $PGVR
-
- runthreads 10 test_brw_write $COUNT_10 -30 $PG
- runthreads 10 test_brw_read $COUNT_10 -30 $PG
-
- [ "$PGVW" ] && runthreads 10 test_brw_write $COUNT_100 -60 $PGVW
- [ "$PGVR" ] && runthreads 10 test_brw_read $COUNT_100 -60 $PGVR
-
- runthreads 32 test_brw_write $COUNT_10 -30 $PG
- runthreads 32 test_brw_read $COUNT_10 -30 $PG
-
- [ "$PGVW" ] && runthreads 32 test_brw_write $COUNT_100 -60 $PGVW
- [ "$PGVR" ] && runthreads 32 test_brw_read $COUNT_100 -60 $PGVR
-
- runthreads 64 test_brw_write $COUNT_10 -30 $PG
- runthreads 64 test_brw_read $COUNT_10 -30 $PG
-
- [ "$PGVW" ] && runthreads 64 test_brw_write $COUNT_100 -60 $PGVW
- [ "$PGVR" ] && runthreads 64 test_brw_read $COUNT_100 -60 $PGVR
-
- runthreads 100 test_brw_write $COUNT_100 -60 $PG
- runthreads 100 test_brw_read $COUNT_100 -60 $PG
-
- [ "$PGVW" ] && runthreads 100 test_brw_write $COUNT_100 -60 $PGVW
- [ "$PGVR" ] && runthreads 100 test_brw_read $COUNT_100 -60 $PGVR
-done
-
-cleanup
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`"
-
-ENDRUN=endrun-`hostname`
-
-fail() {
- echo "ERROR: $1" 1>&2
- [ $2 ] && RC=$2 || RC=1
- exit $RC
-}
-
-export PATH=/sbin:/usr/sbin:$SRCDIR:$PATH
-
-cleanup() {
- trap 0
- $LCONF --cleanup $OPTS
-}
-
-[ "$COUNT" ] || COUNT=1000
-
-[ "$LCONF" ] || LCONF=$SRCDIR/../utils/lconf
-
-[ -z "$*" ] && fail "usage: $0 [--reformat] <conf>.xml" 1
-
-OSCMT="`mount | awk '/ lustre_lite / { print $3 }' | tail -1`"
-if [ -z "$OSCMT" ]; then
- $LCONF $@ || exit 1
- trap cleanup 0
- OSCMT="`mount | awk '/ lustre_lite / { print $3 }' | tail -1`"
- [ -z "$OSCMT" ] && fail "no lustre filesystem mounted" 1
-fi
-
-V="-10"
-while [ "$1" ]; do
- case $1 in
- -v|--verbose) V="1";;
- --reformat) : ;;
- *) OPTS="$OPTS $1" ;;
- esac
- shift
-done
-
-OSCTMP=`echo $OSCMT | tr "/" "."`
-USED=`df | awk "/$OSCTMP/ { print \\$3 }" | tail -1`
-USED=`expr $USED + 16` # Some space for the status file
-
-THREADS=1
-while [ $THREADS -lt 196 ]; do
- echo "starting $THREADS threads at `date`"
- [ $V -gt 0 ] || echo 0 > /proc/sys/portals/debug
- $SRCDIR/createdestroy /mnt/lustre/file-$$ $COUNT $V $THREADS
- $SRCDIR/openclose /mnt/lustre/file-$$ $COUNT $THREADS
- THREADS=`expr $THREADS + 5`
- $LCONF --cleanup $OPTS || fail 10
- $LCONF $OPTS || fail 11
-done
-
-rm -f $ENDRUN
-
-NOWUSED=`df | awk "/$OSCTMP/ { print \\$3 }" | tail -1`
-if [ $NOWUSED -gt $USED ]; then
- echo "Space not all freed: now ${NOWUSED}kB, was ${USED}kB." 1>&2
- echo "This is normal on BA OSTs, because of subdirectories." 1>&2
-fi
-
-cleanup
+++ /dev/null
-#!/bin/sh
-export PATH=/sbin:/usr/sbin:$PATH
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-COUNT=${COUNT:-1000000}
-COUNT_10=`expr $COUNT / 10`
-COUNT_100=`expr $COUNT / 100`
-COUNT_1000=`expr $COUNT / 1000`
-
-ENDRUN=endrun-`hostname`
-
-ECHONAME="`$OBDCTL device_list 2> /dev/null | awk '/ echo_client / { print $4 }' | tail -1`"
-
-if [ -z "$ECHONAME" ]; then
- echo "$0: needs an ECHO_CLIENT set up first" 1>&2
- exit 1
-fi
-
-runthreads() {
- THR=$1
- DO=$2
- CNT=$3
- V=$4
- PGS=$5
-
- case $DO in
- test_getattr)
- RW=
- ;;
-
- test_brw_write)
- DO=test_brw
- RW=w
- ;;
-
- test_brw_read)
- DO=test_brw
- RW=r
- ;;
- esac
-
- $OBDCTL --threads $THR v \$$ECHONAME $DO $CNT $RW $V $PGS $OID || exit 1
-
- if [ -e endrun ]; then
- rm endrun
- echo "exiting because endrun file was found"
- exit 0
- fi
-}
-
-[ -z "$OID" ] && OID=`$OBDCTL --device \\$$ECHONAME create 1 | awk '/is object id/ { print $6 }'`
-[ -z "$OID" ] && echo "error creating object" 1>&2 && exit 1
-
-# TODO: obdctl needs to check on the progress of each forked thread
-# (IPC SHM, sockets?) to see if it hangs.
-for CMD in test_getattr test_brw_write test_brw_read; do
- case $CMD in
- test_getattr)
- PG=
- PGV=
- ;;
- test_brw_write)
- PG=1
- PGV=16
- ;;
- test_brw_read)
- PG=1
- PGV=16
- ;;
- esac
-
- # We use '--threads 1 X' instead of '--device X' so that
- # obdctl can monitor the forked thread for progress (TODO).
- runthreads 1 $CMD 1 1 $PG
- runthreads 1 $CMD 100 1 $PG
-
- debug_server_off
- debug_client_off
- runthreads 1 $CMD $COUNT_100 -10 $PG
- [ "$PGV" ] && runthreads 1 $CMD $COUNT_1000 -10 $PGV
-
- runthreads 1 $CMD $COUNT -30 $PG
- [ "$PGV" ] && runthreads 1 $CMD $COUNT_10 -30 $PGV
-
- runthreads 2 $CMD $COUNT_100 -30 $PG
- [ "$PGV" ] && runthreads 2 $CMD $COUNT_1000 -30 $PGV
-
- runthreads 2 $CMD $COUNT -30 $PG
- [ "$PGV" ] && runthreads 2 $CMD $COUNT_10 -30 $PGV
-
- runthreads 10 $CMD $COUNT_10 -30 $PG
- [ "$PGV" ] && runthreads 10 $CMD $COUNT_100 -30 $PGV
-
- runthreads 100 $CMD $COUNT_100 -30 $PG
- [ "$PGV" ] && runthreads 100 $CMD $COUNT_1000 -30 $PGV
-done
-
-$OBDCTL --device \$$ECHONAME destroy $OID
+++ /dev/null
-#!/bin/sh
-while sleep 1 ; do
- egrep "ll_|ldlm|filp|dentry|inode|portals|size-[0-9]* " /proc/slabinfo
- echo '-----------------------'
-done
+++ /dev/null
-#!/bin/sh
-#
-# Script which does some basic tests to ensure we haven't regressed.
-# Probably a good idea to run this before doing any checkins.
-# In the future this can become more fancy, but it's OK for now.
-
-SRCDIR="`dirname $0`"
-fail() {
- echo "ERROR: $1" 1>&2
- [ $2 ] && RC=$2 || RC=1
- exit $RC
-}
-
-export PATH=/sbin:/usr/sbin:$SRCDIR:$PATH
-
-ERROR=
-SRC=/etc
-[ "$COUNT" ] || COUNT=1000
-
-[ "$LCONF" ] || LCONF=$SRCDIR/../utils/lconf
-
-[ "$MCREATE" ] || MCREATE=$SRCDIR/../tests/mcreate
-
-while [ "$1" ]; do
- case $1 in
- *.xml) export NAME=`echo $1 | sed "s/.xml//"` ;;
- esac
- shift
-done
-
-OSCMT="`mount | awk '/ lustre_lite / { print $3 }' | tail -1`"
-if [ -z "$OSCMT" ]; then
- sh llmount.sh
- OSCMT="`mount | awk '/ lustre_lite / { print $3 }' | tail -1`"
- [ -z "$OSCMT" ] && fail "no lustre filesystem mounted" 1
- I_MOUNTED="yes"
-fi
-
-OSCTMP=`echo $OSCMT | tr "/" "."`
-USED=`df | awk "/$OSCTMP/ { print \\$3 }" | tail -1`
-USED=`expr $USED + 16` # Some space for the status file
-
-# let's start slowly here...
-echo "touching $OSCMT"
-touch $OSCMT || fail "can't touch $OSCMT" 2
-HOSTS=$OSCMT/hosts.$$
-
-# this will cause the following cp to trigger bug #620096
-echo "create an empty file $HOSTS"
-$MCREATE $HOSTS
-
-echo "copying /etc/hosts to $HOSTS"
-cp /etc/hosts $HOSTS || fail "can't cp /etc/hosts to $HOSTS" 3
-echo "comparing /etc/hosts and $HOSTS"
-diff -u /etc/hosts $HOSTS || fail "$HOSTS different" 4
-echo "renaming $HOSTS to $HOSTS.ren"
-mv $HOSTS $HOSTS.ren || fail "can't rename $HOSTS to $HOSTS.ren" 5
-echo "copying /etc/hosts to $HOSTS again"
-cp /etc/hosts $HOSTS || fail "can't cp /etc/hosts to $HOSTS again" 6
-echo "truncating $HOSTS"
-> $HOSTS || fail "can't truncate $HOSTS" 8
-echo "removing $HOSTS"
-rm $HOSTS || fail "can't remove $HOSTS" 9
-
-DST=$OSCMT/runtest.$$
-# let's start slowly here...
-echo "creating $DST"
-mkdir $DST || fail "can't mkdir $DST" 10
-
-# ok, that hopefully worked, so let's do a little more, with files that
-# haven't changed in the last day (hopefully they don't change during test)
-FILES=`find $SRC -type f -mtime +1 -ctime +1 | head -$COUNT`
-echo "copying files from $SRC to $DST$SRC"
-tar cf - $FILES | tar xvf - -C $DST || fail "copying $SRC" 11
-
-echo "comparing newly copied files"
-for f in $FILES; do
- [ $V ] && echo "verifying $DST/$f"
- diff -q $f $DST/$f || ERROR=11
-done
-
-[ "$ERROR" ] && fail "old and new files are different" $ERROR
-
-sh llmountcleanup.sh || exit 19
-sh llrmount.sh || exit 20
-
-echo "comparing previously copied files"
-for f in $FILES; do
- [ $V ] && echo "verifying $DST/$f"
- diff -q $f $DST/$f || ERROR=22
-done
-
-[ "$ERROR" ] && fail "old and new files are different on second diff" $ERROR
-
-sh llmountcleanup.sh || exit 19
-sh llrmount.sh || exit 20
-
-echo "renaming $HOSTS.ren to $HOSTS"
-mv $HOSTS.ren $HOSTS || fail "can't rename $HOSTS.ren to $HOSTS" 32
-echo "truncating $HOSTS"
-> $HOSTS || fail "can't truncate $HOSTS" 34
-echo "removing $HOSTS"
-rm $HOSTS || fail "can't remove $HOSTS again" 36
-echo "removing $DST"
-rm -r $V $DST || fail "can't remove $DST" 37
-
-NOWUSED=`df | awk "/$OSCTMP/ { print \\$3 }" | tail -1`
-if [ $NOWUSED -gt $USED ]; then
- echo "Space not all freed: now ${NOWUSED}kB, was ${USED}kB." 1>&2
- echo "This is normal on BA OSTs, because of subdirectories." 1>&2
-fi
-
-if [ "$I_MOUNTED" = "yes" ]; then
- sh llmountcleanup.sh || exit 29
-fi
+++ /dev/null
-#!/bin/sh
-vmstat 1 | while read LINE ; do echo "`date +%H:%M:%S`: $LINE" ; done
+++ /dev/null
-#!/bin/bash
-
-export NAME=$NAME
-clean() {
- echo -n "cleanup..."
- sh llmountcleanup.sh > /dev/null
-}
-CLEAN=clean
-start() {
- echo -n "mounting..."
- sh llrmount.sh > /dev/null
- echo -n "mounted"
-}
-START=start
-
-echo '== touch .../f ; rm .../f ======================== test 0'
-touch /mnt/lustre/f
-rm /mnt/lustre/f
-$CLEAN
-$START
-
-echo '== mkdir .../d1; mkdir .../d1/d2 ================= test 1'
-mkdir /mnt/lustre/d1
-mkdir /mnt/lustre/d1/d2
-$CLEAN
-$START
-
-echo '== rmdir .../d1/d2; rmdir .../d1 ================= test 1b'
-rmdir /mnt/lustre/d1/d2
-rmdir /mnt/lustre/d1
-$CLEAN
-$START
-
-echo '== mkdir .../d2; touch .../d2/f ================== test 2'
-mkdir /mnt/lustre/d2
-touch /mnt/lustre/d2/f
-$CLEAN
-$START
-
-echo '== rm -r .../d2; touch .../d2/f ================== test 2b'
-rm -r /mnt/lustre/d2
-$CLEAN
-$START
-
-echo '== mkdir .../d3 ================================== test 3'
-mkdir /mnt/lustre/d3
-$CLEAN
-$START
-echo '== touch .../d3/f ================================ test 3b'
-touch /mnt/lustre/d3/f
-$CLEAN
-$START
-echo '== rm -r .../d3 ================================== test 3c'
-rm -r /mnt/lustre/d3
-$CLEAN
-$START
-
-echo '== mkdir .../d4 ================================== test 4'
-mkdir /mnt/lustre/d4
-$CLEAN
-$START
-echo '== mkdir .../d4/d2 =============================== test 4b'
-mkdir /mnt/lustre/d4/d2
-$CLEAN
-$START
-
-echo '== mkdir .../d5; mkdir .../d5/d2; chmod .../d5/d2 = test 5'
-mkdir /mnt/lustre/d5
-mkdir /mnt/lustre/d5/d2
-chmod 0666 /mnt/lustre/d5/d2
-$CLEAN
-$START
-
-echo '== touch .../f6; chmod .../f6 ==================== test 6'
-touch /mnt/lustre/f6
-chmod 0666 /mnt/lustre/f6
-$CLEAN
-$START
-
-echo '== mkdir .../d7; mcreate .../d7/f; chmod .../d7/f = test 7'
-mkdir /mnt/lustre/d7
-./mcreate /mnt/lustre/d7/f
-chmod 0666 /mnt/lustre/d7/f
-$CLEAN
-$START
-
-echo '== mkdir .../d8; touch .../d8/f; chmod .../d8/f == test 8'
-mkdir /mnt/lustre/d8
-touch /mnt/lustre/d8/f
-chmod 0666 /mnt/lustre/d8/f
-$CLEAN
-$START
-
-
-echo '== mkdir .../d9; mkdir .../d9/d2; mkdir .../d9/d2/d3 == test 9'
-mkdir /mnt/lustre/d9
-mkdir /mnt/lustre/d9/d2
-mkdir /mnt/lustre/d9/d2/d3
-$CLEAN
-$START
-
-
-echo '== mkdir .../d10; mkdir .../d10/d2; touch .../d10/d2/f = test 10'
-mkdir /mnt/lustre/d10
-mkdir /mnt/lustre/d10/d2
-touch /mnt/lustre/d10/d2/f
-$CLEAN
-$START
-
-echo '=================================================== test 11'
-mkdir /mnt/lustre/d11
-mkdir /mnt/lustre/d11/d2
-chmod 0666 /mnt/lustre/d11/d2
-chmod 0555 /mnt/lustre/d11/d2
-$CLEAN
-$START
-
-echo '=================================================== test 12'
-mkdir /mnt/lustre/d12
-touch /mnt/lustre/d12/f
-chmod 0666 /mnt/lustre/d12/f
-chmod 0555 /mnt/lustre/d12/f
-$CLEAN
-$START
-
-echo '=================================================== test 13'
-mkdir /mnt/lustre/d13
-cp /etc/passwd /mnt/lustre/d13/f
-> /mnt/lustre/d13/f
-$CLEAN
-$START
-
-
-echo '=================================================== test 14'
-mkdir /mnt/lustre/d14
-touch /mnt/lustre/d14/f
-rm /mnt/lustre/d14/f
-$CLEAN
-$START
-
-
-echo '=================================================== test 15'
-mkdir /mnt/lustre/d15
-touch /mnt/lustre/d15/f
-mv /mnt/lustre/d15/f /mnt/lustre/d15/f2
-$CLEAN
-$START
-
-echo '=================================================== test 16'
-mkdir /mnt/lustre/d16
-touch /mnt/lustre/d16/f
-rm -rf /mnt/lustre/d16/f
-$CLEAN
-$START
-
-echo '== symlinks: create, remove (dangling and real) === test 17'
-mkdir /mnt/lustre/d17
-touch /mnt/lustre/d17/f
-ln -s /mnt/lustre/d17/f /mnt/lustre/d17/l-exist
-ln -s no-such-file /mnt/lustre/d17/l-dangle
-ls -l /mnt/lustre/d17
-rm -f /mnt/lustre/l-dangle
-rm -f /mnt/lustre/l-exist
-$CLEAN
-$START
-
-echo '== touch /mnt/lustre/f ; ls /mnt/lustre ========== test 18'
-touch /mnt/lustre/f
-ls /mnt/lustre
-$CLEAN
-$START
-
-echo '== touch /mnt/lustre/f ; ls -l /mnt/lustre ======= test 19'
-touch /mnt/lustre/f
-ls -l /mnt/lustre
-rm /mnt/lustre/f
-$CLEAN
-$START
-
-echo '== touch /mnt/lustre/f ; ls -l /mnt/lustre ======= test 20'
-touch /mnt/lustre/f
-rm /mnt/lustre/f
-echo "1 done"
-touch /mnt/lustre/f
-rm /mnt/lustre/f
-echo "2 done"
-touch /mnt/lustre/f
-rm /mnt/lustre/f
-echo "3 done"
-$CLEAN
-$START
-
-echo '== write to dangling link ======================= test 21'
-mkdir /mnt/lustre/d21
-ln -s dangle /mnt/lustre/d21/link
-echo foo >> /mnt/lustre/d21/link
-cat /mnt/lustre/d21/dangle
-$CLEAN
-$START
-
-# echo '== unpack tar archive as nonroot user =========== test 22'
-echo '== please fix test 22'
-# mkdir /mnt/lustre/d22
-# chown 4711 /mnt/lustre/d22
-# (./setuid 4711 ; tar cf - /etc/hosts /etc/sysconfig/network | tar xfC - /mnt/lustre/d22 ; ./setuid 0)
-# ls -lR /mnt/lustre/d22/etc
-# $CLEAN
-# $START
-
-echo '== O_CREAT|O_EXCL in subdir ===================== test 23'
-mkdir /mnt/lustre/d23
-./toexcl /mnt/lustre/d23/f23
-./toexcl /mnt/lustre/d23/f23
-$CLEAN
-$START
-
-echo '======================= finished ======================='
-exit
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/fsuid.h>
-
-int main(int argc, char ** argv)
-{
- int rc, fsuid;
-
- if (argc < 2) {
- printf("Usage %s fsuid\n", argv[0]);
- return 1;
- }
-
- fsuid = strtoul(argv[2], NULL, 0);
- rc = setfsuid(fsuid);
- if (rc) {
- printf("mknod(%s) error: %s\n", argv[1], strerror(errno));
- }
- return rc;
-}
+++ /dev/null
-#!/bin/sh
-# Utility script to test several features of a snapshot filesystem
-# Assumes that snapshot has already been configured
-#
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-OBDDIR="`dirname $0`/.."
-. $OBDDIR/demos/config.sh
-
-qrun ls $MNTOBD
-qrun chown bin.bin $MNTOBD
-qrun ls -ld $MNTOBD
-qrun ls -ld $MNTSNAP
-qrun cp /etc/hosts $MNTOBD
-qrun ls $MNTOBD
-qrun ls $MNTSNAP
-
-# More complicated because we can't pass ">>" as an argument easily
-echo -n "Run 'echo today >> $MNTOBD/hello' [Y/n]" ; read JUNK
-case $JUNK in
- n*|N*) echo "not run" ;;
- *) plog log "echo today >> $MNTOBD/hello"
- echo "today" >> $MNTOBD/hello ;;
-esac
-
-qrun cat $MNTOBD/hello
-qrun cat $MNTSNAP/hello
-qrun cat $MNTOBD/link
-qrun cat $MNTSNAP/link
-qrun rm $MNTOBD/goodbye
-qrun ls $MNTOBD
-qrun ls $MNTSNAP
-qrun cat $MNTSNAP/goodbye
+++ /dev/null
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-int main(int argc, char ** argv)
-{
- int rc;
- struct stat buf;
-
- if (argc < 2) {
- printf("Usage %s filename\n", argv[0]);
- return 1;
- }
-
- rc = stat(argv[1], &buf);
- if (rc) {
- printf("stat(%s) error: %s\n", argv[1], strerror(errno));
- }
- return rc;
-}
+++ /dev/null
-# tbox.sh - Shell functions to manage tinderbox build reporting
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Gord Eagle <gord@clusterfs.com>, 2002-08-22
-
-HOSTNAME=`hostname`
-PROGNAME=`echo "$0" | sed -e 's%^.*/%%'`
-MAILPROG="${MAILPROG-mail}"
-
-TBOX_PHASE=build # or test
-TBOX_STARTTIME=`date +%s`
-TBOX_LOG="${TBOX_LOG-/tmp/tbox.$$.$TBOX_STARTTIME.log}"
-TBOX_BUILDMAIL=tinderbox_builds@lustre.org
-TBOX_BUILDNAME="${TBOX_BUILDNAME-$PROGNAME-$HOSTNAME}"
-
-# Send a status message to the list.
-tbox_status() {
- [ -n "$TBOX_BUILDNAME" -a -n "$TBOX_BUILDMAIL" ] || return 0
- [ "$#" -ge 4 ] || return 1
- if [ "$#" -gt 4 ]; then
- log="$5"
- echo >> $log
- else
- log=
- fi
-
- TREE="$1"
- SUBJECT="$2"
- STATUS="$3"
- TIMENOW="$4"
-
- echo "sending tinderbox mail to $TBOX_BUILDMAIL: $TREE $SUBJECT $STATUS"
-
- TMPFILE="/tmp/tinderbox.boilerplate.$$.$TIMENOW"
-
- cat > $TMPFILE <<-EOF
- tinderbox: tree: $TREE
- tinderbox: starttime: $TBOX_STARTTIME
- tinderbox: timenow: $TIMENOW
- tinderbox: builddate: $TBOX_STARTTIME
- tinderbox: status: $STATUS
- tinderbox: buildname: $TBOX_BUILDNAME
- tinderbox: errorparser: unix
- tinderbox: END
-
-EOF
-
- cat $TMPFILE $log | $MAILPROG -s "build $SUBJECT ($TBOX_BUILDNAME)" $TBOX_BUILDMAIL
- rm -f $TMPFILE
-}
-
-# Send out the failure or success message based on exit status.
-tbox_exit() {
- TREE="$1"
- TAILPID="$2"
- CODE=${3-$?}
- if [ $CODE -eq 0 ]; then
- SUBJECT=successful
- STATUS=success
- else
- SUBJECT=failed
- STATUS="${TBOX_PHASE}_failed"
- fi
-
- # Send off the status message.
- trap 0
- tbox_status "$TREE" "$SUBJECT" "$STATUS"
- rm -f $TBOX_LOG
-
- # Wait for tail to display all output, then finish it.
- sleep 1
- kill $TAILPID
- exit $CODE
-}
-
-# Run a subprogram, but stop it from sending its own tinderbox
-# messages.
-tbox_absorb_log() {
- # This probably doesn't do what you think it does... it only prepends
- # TBOX_LOG= to our arguments.
- set TBOX_LOG= "$@"
-
- # Now evaluate the command.
- eval "$@"
-}
-
-# Start the log for a given tree.
-tbox_start_log() {
- TREE="$1"
-
- # Send status messages to stdout, stderr.
- exec 6>&1 7>&2
-
- [ -n "$TBOX_LOG" ] || return 0
-
- # Initialize the output log file.
- : > $TBOX_LOG
-
- # Send all our output to the log.
- exec >>$TBOX_LOG 2>&1
-
- # Monitor it on the old stdout.
- tail -f $TBOX_LOG 1>&6 &
-
- # Allow tail to print our last output before exiting.
- trap "tbox_exit \"$TREE\" $! 1" 1 2 10 15
- trap "tbox_exit \"$TREE\" $!" 0
-}
-
-
-# Begin writing to the log and send out the initial status.
-# tbox_start TREE
-tbox_start() {
- TREE="$1"
- tbox_start_log "$TREE"
- tbox_status "$TREE" starting building "$TBOX_STARTTIME"
-}
+++ /dev/null
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char **argv)
-{
- mode_t mode;
-
- if (argc != 3) {
- printf("usage: %s mode name\n", argv[0]);
- return 1;
- }
-
- mode = strtoul(argv[1], NULL, 8);
- return chmod(argv[2], mode);
-}
+++ /dev/null
-/*
- * Copyright (C) 2001 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <asm/statfs.h>
-#include <unistd.h>
-#include <linux/lustre_idl.h>
-
-#define LOOP_DEVICE "/dev/loop0"
-#define OBD_DEVICE "/dev/obd"
-
-int main (int argc, char * argv[])
-{
- int fd, rc, err = -1;
- struct stat stat_buf;
- struct statfs stfs;
-
-
- if (argc < 2) {
- printf("syntax: %s command [argument]\n", argv[0]);
- printf("Where command is one of \"setup\", \"create\", \"destroy\", or \"sync\".\n");
- exit(1);
- }
- if (stat(LOOP_DEVICE, &stat_buf)) {
- printf("Couldn't stat(" LOOP_DEVICE ").\n");
- exit(1);
- }
- printf("Device: %u\n", (unsigned int) stat_buf.st_rdev);
-
- fd = open (OBD_DEVICE, O_RDONLY);
- if (fd == -1) {
- printf("Couldn't open " OBD_DEVICE ".\n");
- exit(1);
- }
-
- if (!strcmp(argv[1], "setup")) {
- rc = ioctl(fd, OBD_IOC_SETUP, &stat_buf.st_rdev);
- fprintf(stderr, "rc = %d, errno = %d\n", rc, errno);
- } else if (!strcmp(argv[1], "create")) {
- int iter, i;
-
- if (argc < 3) {
- printf("create requires a nonzero argument.\n");
- exit(1);
- }
-
- iter = atoi(argv[2]);
- if (iter < 1) {
- printf("create requires a nonzero argument.\n");
- exit(1);
- }
- printf("creating %d objects...\n", iter);
-
- for (i = 0; i < iter; i++) {
- if ((rc = ioctl(fd, OBD_IOC_CREATE, &err))) {
- fprintf(stderr, "Error; aborting.\n");
- break;
- }
- if ((rc = ioctl(fd, OBD_IOC_DESTROY, &err))) {
- fprintf(stderr, "Error; aborting.\n");
- break;
- }
- }
- fprintf(stderr, "rc = %d, errno = %d, err = %d\n",
- rc, errno, err);
- } else if (!strcmp(argv[1], "sync")) {
- rc = ioctl(fd, OBD_IOC_SYNC, &err);
- fprintf(stderr, "rc = %d, errno = %d, err = %d\n",
- rc, errno, err);
- } else if (!strcmp(argv[1], "destroy")) {
- int ino;
-
- if (argc < 3) {
- printf("destroy requires a nonzero inode number.\n");
- exit(1);
- }
-
- ino = atoi(argv[2]);
- if (ino < 1) {
- printf("destroy requires a nonzero inode number.\n");
- exit(1);
- }
-
- rc = ioctl(fd, OBD_IOC_DESTROY, &ino);
- fprintf(stderr, "rc = %d, errno = %d\n", rc, errno);
- } else {
- printf("Invalid command, run with no arguments for help.\n");
- }
- close(fd);
-
- return 0;
-}
+++ /dev/null
-/*
- * Copyright (C) 2001 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-/* Beware when setting FSROOT that I've not made any attempts to avoid buffer
- * overruns below--this is a test program, it's a static buffer. */
-#define FSROOT "/mnt"
-#define OBD_ITERATIONS 10000
-
-int main (int argc, char * argv[])
-{
- int fd, rc, err = -1;
- struct stat stat_buf;
-
- if (argc < 2) {
- printf("syntax: %s command\n", argv[0]);
- printf("Where command is one of \"setup\" or \"create\".\n");
- exit(1);
- }
-
- if (!strcmp(argv[1], "setup")) {
- printf("This is silly.\n");
- } else if (!strcmp(argv[1], "create")) {
- int i, iter;
-
- if (argc < 3) {
- printf("create requires a nonzero argument.\n");
- exit(1);
- }
-
- iter = atoi(argv[2]);
-
- if (iter < 1) {
- printf("create requires a nonzero argument.\n");
- exit(1);
- }
- printf("creating %d files...\n", iter);
-
- for (i = 0; i < iter; i++) {
- fd = creat(FSROOT "/foo123", S_IRWXU);
- close(fd);
- unlink(FSROOT "/foo123");
- }
- } else {
- printf("Invalid command, run with no arguments for help.\n");
- }
-
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/mman.h>
-
-// not correctly in the headers yet!!
-//#define O_DIRECT 0
-#ifndef O_DIRECT
-#define O_DIRECT 040000 /* direct disk access hint */
-#endif
-
-#define BLOCKSIZE 4096
-#define CERROR(fmt, arg...) fprintf(stderr, fmt, ## arg)
-#ifndef __u64
-#define __u64 long long
-#define HTON__u64(v) (v)
-#endif
-
-#ifndef LPU64
-#define LPU64 "%Lu"
-#define LPX64 "%#Lx"
-#endif
-
-#define READ 1
-#define WRITE 2
-
-#define LPDS sizeof(__u64)
-int page_debug_setup(void *addr, int len, __u64 off, __u64 id)
-{
- off = HTON__u64(off);
- id = HTON__u64(id);
- memcpy(addr, (char *)&off, LPDS);
- memcpy(addr + LPDS, (char *)&id, LPDS);
-
- addr += len - LPDS - LPDS;
- memcpy(addr, (char *)&off, LPDS);
- memcpy(addr + LPDS, (char *)&id, LPDS);
-
- return 0;
-}
-
-int page_debug_check(char *who, void *addr, int size, __u64 off, __u64 id)
-{
- __u64 ne_off;
- int err = 0;
-
- ne_off = HTON__u64(off);
- id = HTON__u64(id);
- if (memcmp(addr, (char *)&ne_off, LPDS)) {
- CERROR("%s: for offset "LPU64" off: "LPX64" != "LPX64"\n",
- who, off, *(__u64 *)addr, ne_off);
- err = -EINVAL;
- }
- if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
- CERROR("%s: for offset "LPU64" id: "LPX64" != "LPX64"\n",
- who, off, *(__u64 *)(addr + LPDS), id);
- err = -EINVAL;
- }
-
- addr += size - LPDS - LPDS;
- if (memcmp(addr, (char *)&ne_off, LPDS)) {
- CERROR("%s: for offset "LPU64" end off: "LPX64" != "LPX64"\n",
- who, off, *(__u64 *)addr, ne_off);
- err = -EINVAL;
- }
- if (memcmp(addr + LPDS, (char *)&id, LPDS)) {
- CERROR("%s: for offset "LPU64" end id: "LPX64" != "LPX64"\n",
- who, off, *(__u64 *)(addr + LPDS), id);
- err = -EINVAL;
- }
-
- return err;
-}
-#undef LPDS
-
-void usage(char *prog)
-{
- fprintf(stderr,
- "usage: %s file count [[d]{r|w|rw} [pages_per_vec [objid]]]\n",
- prog);
- exit(1);
-}
-
-int main(int argc, char **argv)
-{
- int fd;
- char *buf;
- long long count, last, offset;
- long pg_vec, len;
- long long objid = 3;
- int flags = 0;
- int cmd = 0;
- char *end;
- int rc;
-
- if (argc < 3 || argc > 6)
- usage(argv[0]);
-
- count = strtoull(argv[2], &end, 0);
- if (*end) {
- fprintf(stderr, "%s: invalid count '%s'\n", argv[0], argv[2]);
- usage(argv[0]);
- }
- if (argc >= 4) {
- if (strchr(argv[3], 'r')) {
- cmd = READ;
- flags = O_RDONLY;
- }
- if (strchr(argv[3], 'w')) {
- cmd |= WRITE;
- flags = O_RDWR | O_CREAT;
- }
- if (strchr(argv[3], 'd')) {
- flags |= O_DIRECT;
- }
- if (!cmd)
- usage(argv[0]);
- } else {
- cmd = READ | WRITE;
- flags = O_RDWR | O_CREAT | O_DIRECT;
- }
-
- if (argc >= 5) {
- pg_vec = strtoul(argv[4], &end, 0);
- if (*end) {
- fprintf(stderr, "%s: invalid pages_per_vec '%s'\n",
- argv[0], argv[4]);
- usage(argv[0]);
- }
- }
- len = pg_vec * BLOCKSIZE;
- last = (long long)count * len;
-
- if (argc >= 6) {
- objid = strtoull(argv[5], &end, 0);
- if (*end) {
- fprintf(stderr, "%s: invalid objid '%s'\n",
- argv[0], argv[5]);
- usage(argv[0]);
- }
- }
-
- printf("%s: %s on %s(objid "LPX64") for "LPU64"x%ld pages \n",
- argv[0], flags & O_DIRECT ? "directio" : "i/o",
- argv[1], objid, count, pg_vec);
-
- buf = mmap(0, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);
- if (!buf) {
- fprintf(stderr, "%s: no buffer memory %s\n",
- argv[0], strerror(errno));
- return 2;
- }
-
- fd = open(argv[1], flags | O_LARGEFILE);
- if (fd == -1) {
- fprintf(stderr, "%s: cannot open %s: %s\n", argv[0],
- argv[1], strerror(errno));
- return 3;
- }
-
- for (offset = 0; offset < last && cmd & WRITE; offset += len) {
- int i;
-
- for (i = 0; i < len; i += BLOCKSIZE)
- page_debug_setup(buf + i, BLOCKSIZE, offset + i, objid);
-
- rc = write(fd, buf, len);
-
- for (i = 0; i < len; i += BLOCKSIZE) {
- if (page_debug_check("write", buf + i, BLOCKSIZE,
- offset + i, objid))
- return 10;
- }
-
- if (rc != len) {
- fprintf(stderr, "%s: write error: %s, rc %d\n",
- argv[0], strerror(errno), rc);
- return 4;
- }
- }
-
- if (lseek(fd, 0, SEEK_SET) != 0) {
- fprintf(stderr, "%s: cannot seek %s\n",
- argv[0], strerror(errno));
- return 5;
- }
-
- for (offset = 0; offset < last && cmd && READ; offset += len) {
- int i;
-
- rc = read(fd, buf, len);
- if (rc != len) {
- fprintf(stderr, "%s: read error: %s, rc %d\n",
- argv[0], strerror(errno), rc);
- return 6;
- }
-
- for (i = 0; i < len; i += BLOCKSIZE) {
- if (page_debug_check("read", buf + i, BLOCKSIZE,
- offset + i, objid))
- return 11;
- }
- }
-
- return 0;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.sf.net/projects/lustre/
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-
-#define _GNU_SOURCE
-#include <getopt.h>
-#undef _GNU_SOURCE
-
-#include <linux/lustre_mds.h>
-
-static void usage(char *argv0, int status)
-{
- printf(
-"Usage: %s [OPTION...]\n\
-\n\
---getattr <directory>\n\
---setattr <directory>\n\
---readpage <directory>\n\
---open <directory>\n\
---close <directory handle (returned by open)>\n\
---create <new name>\n", argv0);
-
- exit(status);
-}
-
-int main(int argc, char **argv)
-{
- int fd = 0;
- int rc = 0;
- int c = 0;
- long cmd = 0;
- unsigned long arg;
- char *short_opts = "h", *name = argv[0];
- static struct option long_opts[] = {
-#define OPT_GETATTR -2
- {"getattr", no_argument, NULL, OPT_GETATTR},
-#define OPT_READPAGE -3
- {"readpage", no_argument, NULL, OPT_READPAGE},
-#define OPT_SETATTR -4
- {"setattr", no_argument, NULL, OPT_SETATTR},
-#define OPT_CREATE -5
- {"create", no_argument, NULL, OPT_CREATE},
-#define OPT_OPEN -6
- {"open", no_argument, NULL, OPT_OPEN},
-#define OPT_CLOSE -7
- {"close", required_argument, NULL, OPT_CLOSE},
-#define OPT_HELP 'h'
- {"help", no_argument, NULL, OPT_HELP},
- {0}
- };
-
- do {
- c = getopt_long(argc, argv, short_opts, long_opts, NULL);
-
- switch (c) {
- case OPT_HELP:
- usage(argv[0], 0);
- break;
- case OPT_GETATTR:
- cmd = IOC_REQUEST_GETATTR;
- name = "getattr";
- arg = 2;
- break;
- case OPT_SETATTR:
- cmd = IOC_REQUEST_SETATTR;
- name = "setattr";
- arg = 2;
- break;
- case OPT_READPAGE:
- cmd = IOC_REQUEST_READPAGE;
- name = "readpage";
- arg = 2;
- break;
- case OPT_CREATE:
- cmd = IOC_REQUEST_CREATE;
- name ="create";
- arg = 2;
- break;
- case OPT_OPEN:
- cmd = IOC_REQUEST_OPEN;
- name = "open";
- arg = 2;
- break;
- case OPT_CLOSE:
- cmd = IOC_REQUEST_CLOSE;
- name = "close";
- arg = strtoul(optarg, NULL, 0);
- break;
- case '?':
- usage(argv[0], 1);
- }
- } while (c != -1);
-
- if (cmd == 0)
- usage(argv[0], 1);
-
- fd = open("/dev/request", O_RDONLY);
- if (fd == -1) {
- fprintf(stderr, "error opening /dev/request: %s\n",
- strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "Executing %s test (arg=%lu)...\n", name, arg);
- if (cmd == IOC_REQUEST_OPEN) {
- rc = ioctl(fd, cmd, &arg);
- printf("%lu\n", arg);
- } else
- rc = ioctl(fd, cmd, arg);
- fprintf(stderr, "result code: %d\n", rc);
-
- return 0;
-}
+++ /dev/null
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-
-int main(int argc, char **argv)
-{
- int rc;
-
- if (argc != 2) {
- printf("usage: %s name\n", argv[0]);
- return 1;
- }
-
- rc = open(argv[1], O_CREAT|O_EXCL, 0644);
- if (rc == -1)
- printf("open failed: %s\n", strerror(errno));
- else
- printf("open success.\n");
- return 0;
-}
+++ /dev/null
-#!/bin/sh
-# Simple test of mount and unmount
-sh llsetup.sh obdecho.cfg net-local.cfg client-echo.cfg || exit 1
-# FIXME: Scan logs for any unusual things (unbalanced allocations, errors)
-sh llcleanup.sh obdecho.cfg net-local.cfg client-echo.cfg
-OBD_LEAK=`dmesg | awk '/obd memory leaked/ { print $7 }'`
-[ "$OBD_LEAK" != "0" ] && echo "OBD memory leak: $OBD_LEAK bytes" && ERR=1
-NAL_LEAK=`dmesg | awk '/NAL unloaded/ { print $7 }'
-[ "$NAL_LEAK" != "0)" ] && echo "Portals memory leak: $NAL_LEAK" && ERR=1
-/sbin/lsmod | grep -q portals && "Portals module still loaded" && ERR=1
-exit $ERR
+++ /dev/null
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-int main(int argc, char **argv)
-{
- unsigned long long off;
- int err;
-
- if (argc != 3) {
- printf("usage %s file bytes\n", argv[0]);
- return 1;
- }
-
- off = strtoull(argv[2], NULL, 0);
- err = truncate64(argv[1], off);
- if ( err )
- printf("Error truncating %s to %Ld: %s\n", argv[1], off,
- strerror(errno));
-
- return err;
-}
+++ /dev/null
-#!/bin/bash
-
-config=${1-uml.xml}
-LMC=${LMC-../utils/lmc}
-TMP=${TMP:-/tmp}
-
-MDSDEV=$TMP/mds1
-MDSSIZE=50000
-
-OSTDEV1=$TMP/ost1
-OSTDEV2=$TMP/ost2
-OSTSIZE=100000
-
-# NOTE - You can't have different MDS/OST nodes and also have clients on the
-# MDS/OST nodes without using --endlevel and --startlevel during lconf.
-# You can put both MDS/OST on one node and client can be there too.
-# CLIENTS is a space-separated list of client nodes.
-#
-# The rule is that both the MDS and the OST must be set up before any
-# of the clients can be started, so plan accordingly.
-
-# Three separate systems
-MDSNODE=uml1
-OSTNODE=uml2
-CLIENTS="uml3"
-
-# Single system with additional clients
-#MDSNODE=uml1
-#OSTNODE=uml1
-#CLIENTS="$MDSNODE client"
-
-# Two systems with client on MDS, and additional clients (set up OST first)
-#MDSNODE=uml1
-#OSTNODE=uml2
-#CLIENTS="$MDSNODE client"
-
-# Two systems with client on OST, and additional clients (set up MDS first)
-#MDSNODE=uml1
-#OSTNODE=uml2
-#CLIENTS="$OSTNODE client"
-
-rm -f $config
-
-# create nodes
-for NODE in $MDSNODE $OSTNODE $CLIENTS; do
- eval [ \$$NODE ] && continue
- ${LMC} -m $config --node $NODE --net $NODE tcp || exit 1
- eval "$NODE=done"
-done
-
-# configure mds server
-${LMC} -m $config --format --node $MDSNODE --mds mds1 $MDSDEV $MDSSIZE ||exit 10
-
-# configure ost
-${LMC} -m $config --lov lov1 mds1 65536 0 0 || exit 20
-${LMC} -m $config --node $OSTNODE --lov lov1 --ost $OSTDEV1 $OSTSIZE || exit 21
-${LMC} -m $config --node $OSTNODE --lov lov1 --ost $OSTDEV2 $OSTSIZE || exit 22
-
-# create client config(s)
-for NODE in $CLIENTS; do
- ${LMC} -m $config --node $NODE --mtpt /mnt/lustre mds1 lov1 || exit 30
-done
-
+++ /dev/null
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-int main(int argc, char **argv)
-{
- int fd, rc;
- int i = 0;
- char buf[4096];
-
- memset(buf, 0, 4096);
-
- if (argc != 2) {
- printf("Usage openme <filename>\n");
- exit(1);
- }
-
- fd = open(argv[1], O_RDWR | O_CREAT, 0600);
- if (fd == -1) {
- printf("Error opening %s\n", argv[1]);
- exit(1);
- }
-
- while (1) {
- sprintf(buf, "write %d\n", i);
- rc = write(fd, buf, sizeof(buf));
- sleep(1);
- }
- return 0;
-}
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-tags
-TAGS
-obdctl
-lctl
-lfind
-lstripe
+++ /dev/null
-# Administration utilities Makefile
-DEFS=
-
-CFLAGS:=-g -O2 -I$(top_srcdir)/utils -I$(PORTALS)/include -I$(srcdir)/../include -Wall -L$(PORTALSLIB)
-KFLAGS:=
-CPPFLAGS = $(HAVE_LIBREADLINE)
-obdctl_LDADD := $(LIBREADLINE)
-lctl_LDADD := $(LIBREADLINE) -lptlctl
-sbin_PROGRAMS = lctl lfind lstripe obdctl
-sbin_SCRIPTS = lconf lmc
-obdctl_SOURCES = parser.c obdctl.c obd.c parser.h obdctl.h
-lctl_SOURCES = parser.c obd.c lctl.c parser.h
-lfind_SOURCES = lfind.c
-lstripe_SOURCES = lstripe.c
-lfind_CPPFLAGS = -D_XOPEN_SOURCE=500
-EXTRA_DIST = $(sbin_SCRIPTS)
-
-include $(top_srcdir)/Rules
+++ /dev/null
-#!/bin/sh
-
-echo primary `date` >> /tmp/halog
-
-
+++ /dev/null
-#!/bin/bash
-set -vx
-date
-echo "ha assist checking for problems"
-sleep 3
-if [ ! -e /tmp/halog ]; then
- echo "no problems, exiting"
- exit
-fi
-
-echo "removing /tmp/halog"
-rm /tmp/halog
-
-echo secondary start `date`
-echo "- please supply a new mds"
-
-# invoke ldap client here
-
-
-/usr/src/portals/linux/utils/ptlctl <<EOF3
-setup tcp
-close_uuid mds
-del_uuid mds
-connect dev5 988
-add_uuid mds
-quit
-EOF3
-
-echo "connected to new MDS!"
-
-/usr/src/obd/utils/obdctl <<EOF2
-name2dev RPCDEV
-newconn
-quit
-EOF2
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Author: Robert Read <rread@clusterfs.com>
-# This file is part of Lustre, http://www.lustre.org.
-#
-# Lustre is free software; you can redistribute it and/or
-# modify it under the terms of version 2 of the GNU General Public
-# License as published by the Free Software Foundation.
-#
-# Lustre 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 Lustre; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-# lconf - lustre configuration tool
-#
-# lconf is the main driver script for starting and stopping
-# lustre filesystem services.
-#
-# Based in part on the XML obdctl modifications done by Brian Behlendorf
-
-import sys, getopt
-import string, os, stat, popen2, socket, time, random
-import re, exceptions
-import xml.dom.minidom
-
-# Global parameters
-TCP_ACCEPTOR = ''
-MAXTCPBUF = 1048576
-DEFAULT_TCPBUF = 1048576
-#
-# Maximum number of devices to search for.
-# (the /dev/loop* nodes need to be created beforehand)
-MAX_LOOP_DEVICES = 256
-
-first_cleanup_error = 0
-def cleanup_error(rc):
- global first_cleanup_error
- if not first_cleanup_error:
- first_cleanup_error = rc
-
-
-def usage():
- print """usage: lconf config.xml
-
-config.xml Lustre configuration in xml format.
---get <url> URL to fetch a config file
---node <nodename> Load config for <nodename>
--d | --cleanup Cleans up config. (Shutdown)
--f | --force Forced unmounting and/or obd detach during cleanup
--v | --verbose Print system commands as they are run
--h | --help Print this help
---gdb Prints message after creating gdb module script
- and sleeps for 5 seconds.
--n | --noexec Prints the commands and steps that will be run for a
- config without executing them. This can used to check if a
- config file is doing what it should be doing. (Implies -v)
---nomod Skip load/unload module step.
---nosetup Skip device setup/cleanup step.
---reformat Reformat all devices (without question)
---dump <file> Dump the kernel debug log before portals is unloaded
---minlevel <num> Specify the minimum level of services to configure/cleanup (default 0)
---maxlevel <num> Specify the maximum level of services to configure/cleanup (default 100)
- Levels are aproximatly like:
- 10 - network
- 20 - device, ldlm
- 30 - obd, mdd
- 40 - mds, ost
- 50 - mdc, osc
- 60 - lov, lovconfig
- 70 - mountpoint, echo_client
-"""
- TODO = """
---ldap server LDAP server with lustre config database
---makeldiff Translate xml source to LDIFF
-This are perhaps not needed:
---lustre="src dir" Base directory of lustre sources. Used to search
- for modules.
---portals=src Portals source
-"""
- sys.exit()
-
-# ============================================================
-# Config parameters, encapsulated in a class
-class Config:
- def __init__(self):
- # flags
- self._noexec = 0
- self._verbose = 0
- self._reformat = 0
- self._cleanup = 0
- self._gdb = 0
- self._nomod = 0
- self._nosetup = 0
- self._force = 0
- # parameters
- self._modules = None
- self._node = None
- self._url = None
- self._gdb_script = '/tmp/ogdb'
- self._debug_path = '/tmp/lustre-log'
- self._dump_file = None
- self._src_dir = None
- self._minlevel = 0
- self._maxlevel = 100
-
- def verbose(self, flag = None):
- if flag: self._verbose = flag
- return self._verbose
-
- def noexec(self, flag = None):
- if flag: self._noexec = flag
- return self._noexec
-
- def reformat(self, flag = None):
- if flag: self._reformat = flag
- return self._reformat
-
- def cleanup(self, flag = None):
- if flag: self._cleanup = flag
- return self._cleanup
-
- def gdb(self, flag = None):
- if flag: self._gdb = flag
- return self._gdb
-
- def nomod(self, flag = None):
- if flag: self._nomod = flag
- return self._nomod
-
- def nosetup(self, flag = None):
- if flag: self._nosetup = flag
- return self._nosetup
-
- def force(self, flag = None):
- if flag: self._force = flag
- return self._force
-
- def node(self, val = None):
- if val: self._node = val
- return self._node
-
- def url(self, val = None):
- if val: self._url = val
- return self._url
-
- def gdb_script(self):
- if os.path.isdir('/r'):
- return '/r' + self._gdb_script
- else:
- return self._gdb_script
-
- def debug_path(self):
- if os.path.isdir('/r'):
- return '/r' + self._debug_path
- else:
- return self._debug_path
-
- def src_dir(self, val = None):
- if val: self._src_dir = val
- return self._src_dir
-
- def dump_file(self, val = None):
- if val: self._dump_file = val
- return self._dump_file
-
- def minlevel(self, val = None):
- if val: self._minlevel = int(val)
- return self._minlevel
-
- def maxlevel(self, val = None):
- if val: self._maxlevel = int(val)
- return self._maxlevel
-
-
-
-config = Config()
-
-# ============================================================
-# debugging and error funcs
-
-def fixme(msg = "this feature"):
- raise LconfError, msg + ' not implmemented yet.'
-
-def panic(*args):
- msg = string.join(map(str,args))
- if not config.noexec():
- raise LconfError(msg)
- else:
- print "! " + msg
-
-def log(*args):
- msg = string.join(map(str,args))
- print msg
-
-def logall(msgs):
- for s in msgs:
- print string.strip(s)
-
-def debug(*args):
- if config.verbose():
- msg = string.join(map(str,args))
- print msg
-
-# ============================================================
-# locally defined exceptions
-class CommandError (exceptions.Exception):
- def __init__(self, cmd_name, cmd_err, rc=None):
- self.cmd_name = cmd_name
- self.cmd_err = cmd_err
- self.rc = rc
-
- def dump(self):
- import types
- if type(self.cmd_err) == types.StringType:
- if self.rc:
- print "! %s (%d): %s" % (self.cmd_name, self.rc, self.cmd_err)
- else:
- print "! %s: %s" % (self.cmd_name, self.cmd_err)
- elif type(self.cmd_err) == types.ListType:
- if self.rc:
- print "! %s (error %d):" % (self.cmd_name, self.rc)
- else:
- print "! %s:" % (self.cmd_name)
- for s in self.cmd_err:
- print "> %s" %(string.strip(s))
- else:
- print self.cmd_err
-
-class LconfError (exceptions.Exception):
- def __init__(self, args):
- self.args = args
-
-
-# ============================================================
-# handle lctl interface
-class LCTLInterface:
- """
- Manage communication with lctl
- """
-
- def __init__(self, cmd):
- """
- Initialize close by finding the lctl binary.
- """
- self.lctl = find_prog(cmd)
- if not self.lctl:
- if config.noexec():
- debug('! lctl not found')
- self.lctl = 'lctl'
- else:
- raise CommandError('lctl', "unable to find lctl binary.")
-
- def run(self, cmds):
- """
- run lctl
- the cmds are written to stdin of lctl
- lctl doesn't return errors when run in script mode, so
- stderr is checked
- should modify command line to accept multiple commands, or
- create complex command line options
- """
- debug("+", self.lctl, cmds)
- if config.noexec(): return (0, [])
- p = popen2.Popen3(self.lctl, 1)
- p.tochild.write(cmds + "\n")
- p.tochild.close()
- out = p.fromchild.readlines()
- err = p.childerr.readlines()
- ret = p.wait()
- if os.WIFEXITED(ret):
- rc = os.WEXITSTATUS(ret)
- else:
- rc = 0
- if rc or len(err):
- raise CommandError(self.lctl, err, rc)
- return rc, out
-
- def runcmd(self, *args):
- """
- run lctl using the command line
- """
- cmd = string.join(map(str,args))
- debug("+", self.lctl, cmd)
- rc, out = run(self.lctl, cmd)
- if rc:
- raise CommandError(self.lctl, out, rc)
- return rc, out
-
-
- def network(self, net, nid):
- """ initialized network and add "self" """
- # Idea: "mynid" could be used for all network types to add "self," and then
- # this special case would be gone and the "self" hack would be hidden.
- if net in ('tcp', 'toe'):
- cmds = """
- network %s
- mynid %s
- add_uuid self %s
- quit""" % (net, nid, nid)
- else:
- cmds = """
- network %s
- add_uuid self %s
- quit""" % (net, nid)
-
- self.run(cmds)
-
- # create a new connection
- def connect(self, net, nid, port, servuuid, send_mem, recv_mem):
- if net in ('tcp', 'toe'):
- cmds = """
- network %s
- add_uuid %s %s
- send_mem %d
- recv_mem %d
- connect %s %d
- quit""" % (net, servuuid, nid, send_mem, recv_mem, nid, port, )
- else:
- cmds = """
- network %s
- add_uuid %s %s
- connect %s %d
- quit""" % (net, servuuid, nid, nid, port, )
-
- self.run(cmds)
-
- # add a route to a range
- def add_route(self, net, gw, lo, hi):
- cmds = """
- network %s
- add_route %s %s %s
- quit """ % (net, gw, lo, hi)
- self.run(cmds)
-
-
- def del_route(self, net, gw, lo, hi):
- cmds = """
- ignore_errors
- network %s
- del_route %s
- quit """ % (net, lo)
- self.run(cmds)
-
- # add a route to a host
- def add_route_host(self, net, uuid, gw, tgt):
- cmds = """
- network %s
- add_uuid %s %s
- add_route %s %s
- quit """ % (net, uuid, tgt, gw, tgt)
- self.run(cmds)
-
- # add a route to a range
- def del_route_host(self, net, uuid, gw, tgt):
- cmds = """
- ignore_errors
- network %s
- del_uuid %s
- del_route %s
- quit """ % (net, uuid, tgt)
- self.run(cmds)
-
- # disconnect one connection
- def disconnect(self, net, nid, port, servuuid):
- cmds = """
- ignore_errors
- network %s
- disconnect %s
- del_uuid %s
- quit""" % (net, nid, servuuid)
- self.run(cmds)
-
- # disconnect all
- def disconnectAll(self, net):
- cmds = """
- ignore_errors
- network %s
- del_uuid self
- disconnect
- quit""" % (net)
- self.run(cmds)
-
- # create a new device with lctl
- def newdev(self, attach, setup = ""):
- cmds = """
- newdev
- attach %s
- setup %s
- quit""" % (attach, setup)
- self.run(cmds)
-
- # cleanup a device
- def cleanup(self, name, uuid):
- cmds = """
- ignore_errors
- device $%s
- cleanup
- detach %s
- quit""" % (name, ('', 'force')[config.force()])
- self.run(cmds)
-
- # create an lov
- def lov_setconfig(self, uuid, mdsuuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist):
- cmds = """
- device $%s
- probe
- lov_setconfig %s %d %d %d %s %s
- quit""" % (mdsuuid, uuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist)
- self.run(cmds)
-
- # dump the log file
- def dump(self, dump_file):
- cmds = """
- debug_kernel %s 1
- quit""" % (dump_file)
- self.run(cmds)
-
- # get list of devices
- def device_list(self):
- rc, out = self.runcmd('device_list')
- return out
-
- # get lustre version
- def lustre_version(self):
- rc, out = self.runcmd('version')
- return out
-
-# ============================================================
-# Various system-level functions
-# (ideally moved to their own module)
-
-# Run a command and return the output and status.
-# stderr is sent to /dev/null, could use popen3 to
-# save it if necessary
-def run(*args):
- cmd = string.join(map(str,args))
- debug ("+", cmd)
- if config.noexec(): return (0, [])
- f = os.popen(cmd + ' 2>&1')
- out = f.readlines()
- ret = f.close()
- if ret:
- ret = ret >> 8
- else:
- ret = 0
- return (ret, out)
-
-# Run a command in the background.
-def run_daemon(*args):
- cmd = string.join(map(str,args))
- debug ("+", cmd)
- if config.noexec(): return 0
- f = os.popen(cmd + ' 2>&1')
- ret = f.close()
- if ret:
- ret = ret >> 8
- else:
- ret = 0
- return ret
-
-# Determine full path to use for an external command
-# searches dirname(argv[0]) first, then PATH
-def find_prog(cmd):
- syspath = string.split(os.environ['PATH'], ':')
- cmdpath = os.path.dirname(sys.argv[0])
- syspath.insert(0, cmdpath);
- syspath.insert(0, os.path.join(cmdpath, '../../portals/linux/utils/'))
- for d in syspath:
- prog = os.path.join(d,cmd)
- if os.access(prog, os.X_OK):
- return prog
- return ''
-
-# Recursively look for file starting at base dir
-def do_find_file(base, mod):
- fullname = os.path.join(base, mod)
- if os.access(fullname, os.R_OK):
- return fullname
- for d in os.listdir(base):
- dir = os.path.join(base,d)
- if os.path.isdir(dir):
- module = do_find_file(dir, mod)
- if module:
- return module
-
-def find_module(src_dir, dev_dir, modname):
- mod = '%s.o' % (modname)
- module = src_dir +'/'+ dev_dir +'/'+ mod
- try:
- if os.access(module, os.R_OK):
- return module
- except OSError:
- pass
- return None
-
-# is the path a block device?
-def is_block(path):
- s = ()
- try:
- s = os.stat(path)
- except OSError:
- return 0
- return stat.S_ISBLK(s[stat.ST_MODE])
-
-# build fs according to type
-# fixme: dangerous
-def mkfs(fstype, dev):
- if(fstype in ('ext3', 'extN')):
- mkfs = 'mkfs.ext2 -j -b 4096'
- else:
- print 'unsupported fs type: ', fstype
- if not is_block(dev):
- force = '-F'
- else:
- force = ''
- (ret, out) = run (mkfs, force, dev)
- if ret:
- panic("Unable to build fs:", dev)
- # enable hash tree indexing on fsswe
- # FIXME: this check can probably go away on 2.5
- if fstype == 'extN':
- htree = 'echo "feature FEATURE_C5" | debugfs -w'
- (ret, out) = run (htree, dev)
- if ret:
- panic("Unable to enable htree:", dev)
-
-# some systems use /dev/loopN, some /dev/loop/N
-def loop_base():
- import re
- loop = '/dev/loop'
- if not os.access(loop + str(0), os.R_OK):
- loop = loop + '/'
- if not os.access(loop + str(0), os.R_OK):
- panic ("can't access loop devices")
- return loop
-
-# find loop device assigned to thefile
-def find_loop(file):
- loop = loop_base()
- for n in xrange(0, MAX_LOOP_DEVICES):
- dev = loop + str(n)
- if os.access(dev, os.R_OK):
- (stat, out) = run('losetup', dev)
- if (out and stat == 0):
- m = re.search(r'\((.*)\)', out[0])
- if m and file == m.group(1):
- return dev
- else:
- break
- return ''
-
-# create file if necessary and assign the first free loop device
-def init_loop(file, size, fstype):
- dev = find_loop(file)
- if dev:
- print 'WARNING file:', file, 'already mapped to', dev
- return dev
- if config.reformat() or not os.access(file, os.R_OK | os.W_OK):
- run("dd if=/dev/zero bs=1k count=0 seek=%d of=%s" %(size, file))
- loop = loop_base()
- # find next free loop
- for n in xrange(0, MAX_LOOP_DEVICES):
- dev = loop + str(n)
- if os.access(dev, os.R_OK):
- (stat, out) = run('losetup', dev)
- if (stat):
- run('losetup', dev, file)
- return dev
- else:
- print "out of loop devices"
- return ''
- print "out of loop devices"
- return ''
-
-# undo loop assignment
-def clean_loop(file):
- dev = find_loop(file)
- if dev:
- ret, out = run('losetup -d', dev)
- if ret:
- log('unable to clean loop device:', dev, 'for file:', file)
- logall(out)
-
-# determine if dev is formatted as a <fstype> filesystem
-def need_format(fstype, dev):
- # FIXME don't know how to implement this
- return 0
-
-# initialize a block device if needed
-def block_dev(dev, size, fstype, format):
- if config.noexec(): return dev
- if not is_block(dev):
- dev = init_loop(dev, size, fstype)
- if config.reformat() or (need_format(fstype, dev) and format == 'yes'):
- mkfs(fstype, dev)
-
-# else:
-# panic("device:", dev,
-# "not prepared, and autoformat is not set.\n",
-# "Rerun with --reformat option to format ALL filesystems")
-
- return dev
-
-def if2addr(iface):
- """lookup IP address for an interface"""
- rc, out = run("/sbin/ifconfig", iface)
- if rc or not out:
- return None
- addr = string.split(out[1])[1]
- ip = string.split(addr, ':')[1]
- return ip
-
-def get_local_address(net_type, wildcard):
- """Return the local address for the network type."""
- local = ""
- if net_type in ('tcp', 'toe'):
- if ':' in wildcard:
- iface, star = string.split(wildcard, ':')
- local = if2addr(iface)
- if not local:
- panic ("unable to determine ip for:", wildcard)
- else:
- host = socket.gethostname()
- local = socket.gethostbyname(host)
- elif net_type == 'elan':
- # awk '/NodeId/ { print $2 }' '/proc/elan/device0/position'
- try:
- fp = open('/proc/elan/device0/position', 'r')
- lines = fp.readlines()
- fp.close()
- for l in lines:
- a = string.split(l)
- if a[0] == 'NodeId':
- local = a[1]
- break
- except IOError, e:
- log(e)
- elif net_type == 'gm':
- fixme("automatic local address for GM")
- return local
-
-
-def is_prepared(uuid):
- """Return true if a device exists for the uuid"""
- # expect this format:
- # 1 UP ldlm ldlm ldlm_UUID 2
- try:
- out = lctl.device_list()
- for s in out:
- if uuid == string.split(s)[4]:
- return 1
- except CommandError, e:
- e.dump()
- return 0
-
-
-# ============================================================
-# Classes to prepare and cleanup the various objects
-#
-class Module:
- """ Base class for the rest of the modules. The default cleanup method is
- defined here, as well as some utilitiy funcs.
- """
- def __init__(self, module_name, dom_node):
- self.dom_node = dom_node
- self.module_name = module_name
- self.name = get_attr(dom_node, 'name')
- self.uuid = get_attr(dom_node, 'uuid')
- self.kmodule_list = []
- self._server = None
- self._connected = 0
-
- def info(self, *args):
- msg = string.join(map(str,args))
- print self.module_name + ":", self.name, self.uuid, msg
-
-
- def lookup_server(self, srv_uuid):
- """ Lookup a server's network information """
- net = get_ost_net(self.dom_node.parentNode, srv_uuid)
- if not net:
- panic ("Unable to find a server for:", srv_uuid)
- self._server = Network(net)
-
- def get_server(self):
- return self._server
-
- def cleanup(self):
- """ default cleanup, used for most modules """
- self.info()
- srv = self.get_server()
- if srv and local_net(srv):
- try:
- lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
- except CommandError, e:
- log(self.module_name, "disconnect failed: ", self.name)
- e.dump()
- cleanup_error(e.rc)
- try:
- lctl.cleanup(self.name, self.uuid)
- except CommandError, e:
- log(self.module_name, "cleanup failed: ", self.name)
- e.dump()
- cleanup_error(e.rc)
-
- def add_module(self, dev_dir, modname):
- """Append a module to list of modules to load."""
- self.kmodule_list.append((dev_dir, modname))
-
- def mod_loaded(self, modname):
- """Check if a module is already loaded. Look in /proc/modules for it."""
- fp = open('/proc/modules')
- lines = fp.readlines()
- fp.close()
- # please forgive my tired fingers for this one
- ret = filter(lambda word, mod=modname: word == mod,
- map(lambda line: string.split(line)[0], lines))
- return ret
-
- def load_module(self):
- """Load all the modules in the list in the order they appear."""
- for dev_dir, mod in self.kmodule_list:
- # (rc, out) = run ('/sbin/lsmod | grep -s', mod)
- if self.mod_loaded(mod) and not config.noexec():
- continue
- log ('loading module:', mod)
- if config.src_dir():
- module = find_module(config.src_dir(),dev_dir, mod)
- if not module:
- panic('module not found:', mod)
- (rc, out) = run('/sbin/insmod', module)
- if rc:
- raise CommandError('insmod', out, rc)
- else:
- (rc, out) = run('/sbin/modprobe', mod)
- if rc:
- raise CommandError('modprobe', out, rc)
-
- def cleanup_module(self):
- """Unload the modules in the list in reverse order."""
- rev = self.kmodule_list
- rev.reverse()
- for dev_dir, mod in rev:
- if not self.mod_loaded(mod):
- continue
- # debug hack
- if mod == 'portals' and config.dump_file():
- lctl.dump(config.dump_file())
- log('unloading module:', mod)
- if config.noexec():
- continue
- (rc, out) = run('/sbin/rmmod', mod)
- if rc:
- log('! unable to unload module:', mod)
- logall(out)
-
-
-class Network(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'NETWORK', dom_node)
- self.net_type = get_attr(dom_node,'type')
- self.nid = get_text(dom_node, 'server', '*')
- self.port = get_text_int(dom_node, 'port', 0)
- self.send_mem = get_text_int(dom_node, 'send_mem', DEFAULT_TCPBUF)
- self.recv_mem = get_text_int(dom_node, 'recv_mem', DEFAULT_TCPBUF)
- if '*' in self.nid:
- self.nid = get_local_address(self.net_type, self.nid)
- if not self.nid:
- panic("unable to set nid for", self.net_type, self.nid)
- debug("nid:", self.nid)
-
- self.add_module('portals/linux/oslib/', 'portals')
- if node_needs_router():
- self.add_module('portals/linux/router', 'kptlrouter')
- if self.net_type == 'tcp':
- self.add_module('portals/linux/socknal', 'ksocknal')
- if self.net_type == 'toe':
- self.add_module('portals/linux/toenal', 'ktoenal')
- if self.net_type == 'elan':
- self.add_module('portals/linux/rqswnal', 'kqswnal')
- if self.net_type == 'gm':
- self.add_module('portals/linux/gmnal', 'kgmnal')
- self.add_module('lustre/obdclass', 'obdclass')
- self.add_module('lustre/ptlrpc', 'ptlrpc')
-
- def prepare(self):
- self.info(self.net_type, self.nid, self.port)
- if self.net_type in ('tcp', 'toe'):
- nal_id = '' # default is socknal
- if self.net_type == 'toe':
- nal_id = '-N 4'
- ret, out = run(TCP_ACCEPTOR, '-s', self.send_mem, '-r', self.recv_mem, nal_id, self.port)
- if ret:
- raise CommandError(TCP_ACCEPTOR, out, ret)
- ret = self.dom_node.getElementsByTagName('route_tbl')
- for a in ret:
- for r in a.getElementsByTagName('route'):
- net_type = get_attr(r, 'type')
- gw = get_attr(r, 'gw')
- lo = get_attr(r, 'lo')
- hi = get_attr(r,'hi', '')
- lctl.add_route(net_type, gw, lo, hi)
- if net_type in ('tcp', 'toe') and net_type == self.net_type and hi == '':
- srv = nid2server(self.dom_node.parentNode.parentNode, lo)
- if not srv:
- panic("no server for nid", lo)
- else:
- lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
-
-
- lctl.network(self.net_type, self.nid)
- lctl.newdev(attach = "ptlrpc RPCDEV RPCDEV_UUID")
-
- def cleanup(self):
- self.info(self.net_type, self.nid, self.port)
- ret = self.dom_node.getElementsByTagName('route_tbl')
- for a in ret:
- for r in a.getElementsByTagName('route'):
- lo = get_attr(r, 'lo')
- hi = get_attr(r,'hi', '')
- if self.net_type in ('tcp', 'toe') and hi == '':
- srv = nid2server(self.dom_node.parentNode.parentNode, lo)
- if not srv:
- panic("no server for nid", lo)
- else:
- try:
- lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
- except CommandError, e:
- print "disconnect failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- try:
- lctl.del_route(self.net_type, self.nid, lo, hi)
- except CommandError, e:
- print "del_route failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
-
- try:
- lctl.cleanup("RPCDEV", "RPCDEV_UUID")
- except CommandError, e:
- print "cleanup failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- try:
- lctl.disconnectAll(self.net_type)
- except CommandError, e:
- print "disconnectAll failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- if self.net_type in ('tcp', 'toe'):
- # yikes, this ugly! need to save pid in /var/something
- run("killall acceptor")
-
-class LDLM(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LDLM', dom_node)
- self.add_module('lustre/ldlm', 'ldlm')
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info()
- lctl.newdev(attach="ldlm %s %s" % (self.name, self.uuid),
- setup ="")
-
-class LOV(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LOV', dom_node)
- self.mds_uuid = get_first_ref(dom_node, 'mds')
- mds= lookup(dom_node.parentNode, self.mds_uuid)
- self.mds_name = getName(mds)
- devs = dom_node.getElementsByTagName('devices')
- if len(devs) > 0:
- dev_node = devs[0]
- self.stripe_sz = get_attr_int(dev_node, 'stripesize', 65536)
- self.stripe_off = get_attr_int(dev_node, 'stripeoffset', 0)
- self.pattern = get_attr_int(dev_node, 'pattern', 0)
- self.devlist = get_all_refs(dev_node, 'osc')
- self.stripe_cnt = get_attr_int(dev_node, 'stripecount', len(self.devlist))
- self.add_module('lustre/mdc', 'mdc')
- self.add_module('lustre/lov', 'lov')
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- try:
- # Ignore connection failures, because the LOV will DTRT with
- # an unconnected OSC.
- n.prepare(ignore_connect_failure=1)
- except CommandError:
- print "Error preparing OSC %s (inactive)\n" % osc_uuid
- else:
- panic('osc not found:', osc_uuid)
- mdc_uuid = prepare_mdc(self.dom_node.parentNode, self.mds_uuid)
- self.info(self.mds_uuid, self.stripe_cnt, self.stripe_sz,
- self.stripe_off, self.pattern, self.devlist, self.mds_name)
- lctl.newdev(attach="lov %s %s" % (self.name, self.uuid),
- setup ="%s" % (mdc_uuid))
-
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- n.cleanup()
- else:
- panic('osc not found:', osc_uuid)
- Module.cleanup(self)
- cleanup_mdc(self.dom_node.parentNode, self.mds_uuid)
-
-
- def load_module(self):
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- n.load_module()
- break
- else:
- panic('osc not found:', osc_uuid)
- Module.load_module(self)
-
-
- def cleanup_module(self):
- Module.cleanup_module(self)
- for osc_uuid in self.devlist:
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- n.cleanup_module()
- break
- else:
- panic('osc not found:', osc_uuid)
-
-class LOVConfig(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'LOVConfig', dom_node)
- self.lov_uuid = get_first_ref(dom_node, 'lov')
- l = lookup(dom_node.parentNode, self.lov_uuid)
- self.lov = LOV(l)
-
- def prepare(self):
- lov = self.lov
- self.info(lov.mds_uuid, lov.stripe_cnt, lov.stripe_sz, lov.stripe_off,
- lov.pattern, lov.devlist, lov.mds_name)
- lctl.lov_setconfig(lov.uuid, lov.mds_name, lov.stripe_cnt,
- lov.stripe_sz, lov.stripe_off, lov.pattern,
- string.join(lov.devlist))
-
- def cleanup(self):
- #nothing to do here
- pass
-
-
-class MDS(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'MDS', dom_node)
- self.devname, self.size = get_device(dom_node)
- self.fstype = get_text(dom_node, 'fstype')
- # FIXME: if fstype not set, then determine based on kernel version
- self.format = get_text(dom_node, 'autoformat', "no")
- if self.fstype == 'extN':
- self.add_module('lustre/extN', 'extN')
- self.add_module('lustre/mds', 'mds')
- self.add_module('lustre/mds', 'mds_%s' % (self.fstype))
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.devname, self.fstype, self.format)
- blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
- if not is_prepared('MDT_UUID'):
- lctl.newdev(attach="mdt %s %s" % ('MDT', 'MDT_UUID'),
- setup ="")
- lctl.newdev(attach="mds %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(blkdev, self.fstype))
- def cleanup(self):
- if is_prepared('MDT_UUID'):
- try:
- lctl.cleanup("MDT", "MDT_UUID")
- except CommandError, e:
- print "cleanup failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- if not is_prepared(self.uuid):
- return
- Module.cleanup(self)
- clean_loop(self.devname)
-
-# Very unusual case, as there is no MDC element in the XML anymore
-# Builds itself from an MDS node
-class MDC(Module):
- def __init__(self,dom_node):
- self.mds = MDS(dom_node)
- self.dom_node = dom_node
- self.module_name = 'MDC'
- self.kmodule_list = []
- self._server = None
- self._connected = 0
-
- host = socket.gethostname()
- self.name = 'MDC_%s' % (self.mds.name)
- self.uuid = '%s_%05x_%05x' % (self.name, int(random.random() * 1048576),
- int(random.random() * 1048576))
-
- self.lookup_server(self.mds.uuid)
- self.add_module('lustre/mdc', 'mdc')
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.mds.uuid)
- srv = self.get_server()
- lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
- lctl.newdev(attach="mdc %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(self.mds.uuid, srv.uuid))
-
-class OBD(Module):
- def __init__(self, dom_node):
- Module.__init__(self, 'OBD', dom_node)
- self.obdtype = get_attr(dom_node, 'type')
- self.devname, self.size = get_device(dom_node)
- self.fstype = get_text(dom_node, 'fstype')
- # FIXME: if fstype not set, then determine based on kernel version
- self.format = get_text(dom_node, 'autoformat', 'yes')
- if self.fstype == 'extN':
- self.add_module('lustre/extN', 'extN')
- self.add_module('lustre/' + self.obdtype, self.obdtype)
-
- # need to check /proc/mounts and /etc/mtab before
- # formatting anything.
- # FIXME: check if device is already formatted.
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.obdtype, self.devname, self.size, self.fstype, self.format)
- if self.obdtype == 'obdecho':
- blkdev = ''
- else:
- blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
- lctl.newdev(attach="%s %s %s" % (self.obdtype, self.name, self.uuid),
- setup ="%s %s" %(blkdev, self.fstype))
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- Module.cleanup(self)
- if not self.obdtype == 'obdecho':
- clean_loop(self.devname)
-
-class OST(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'OST', dom_node)
- self.obd_uuid = get_first_ref(dom_node, 'obd')
- self.add_module('lustre/ost', 'ost')
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.info(self.obd_uuid)
- lctl.newdev(attach="ost %s %s" % (self.name, self.uuid),
- setup ="%s" % (self.obd_uuid))
-
-
-# virtual interface for OSC and LOV
-class VOSC(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'VOSC', dom_node)
- if dom_node.nodeName == 'lov':
- self.osc = LOV(dom_node)
- else:
- self.osc = OSC(dom_node)
- def prepare(self):
- self.osc.prepare()
- def cleanup(self):
- self.osc.cleanup()
- def load_module(self):
- self.osc.load_module()
- def cleanup_module(self):
- self.osc.cleanup_module()
-
-
-class OSC(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'OSC', dom_node)
- self.obd_uuid = get_first_ref(dom_node, 'obd')
- self.ost_uuid = get_first_ref(dom_node, 'ost')
- self.lookup_server(self.ost_uuid)
- self.add_module('lustre/osc', 'osc')
-
- def prepare(self, ignore_connect_failure = 0):
- if is_prepared(self.uuid):
- return
- self.info(self.obd_uuid, self.ost_uuid)
- srv = self.get_server()
- try:
- if local_net(srv):
- lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_mem, srv.recv_mem)
- else:
- r = find_route(srv)
- if r:
- lctl.add_route_host(r[0], srv.uuid, r[1], r[2])
- else:
- panic ("no route to", srv.nid)
- except CommandError:
- if (ignore_connect_failure == 0):
- pass
-
- lctl.newdev(attach="osc %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(self.obd_uuid, srv.uuid))
-
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- srv = self.get_server()
- if local_net(srv):
- Module.cleanup(self)
- else:
- self.info(self.obd_uuid, self.ost_uuid)
- r = find_route(srv)
- if r:
- try:
- lctl.del_route_host(r[0], srv.uuid, r[1], r[2])
- except CommandError, e:
- print "del_route failed: ", self.name
- e.dump()
- cleanup_error(e.rc)
- Module.cleanup(self)
-
-
-class ECHO_CLIENT(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'ECHO_CLIENT', dom_node)
- self.add_module('lustre/obdecho', 'obdecho')
- self.lov_uuid = get_first_ref(dom_node, 'osc')
- l = lookup(self.dom_node.parentNode, self.lov_uuid)
- self.osc = VOSC(l)
-
- def prepare(self):
- if is_prepared(self.uuid):
- return
- self.osc.prepare() # XXX This is so cheating. -p
- self.info(self.lov_uuid)
-
- lctl.newdev(attach="echo_client %s %s" % (self.name, self.uuid),
- setup = self.lov_uuid)
-
- def cleanup(self):
- if not is_prepared(self.uuid):
- return
- self.osc.cleanup()
-
- def load_module(self):
- self.osc.load_module()
- Module.load_module(self)
- def cleanup_module(self):
- Module.cleanup_module(self)
- self.osc.cleanup_module()
-
-
-class Mountpoint(Module):
- def __init__(self,dom_node):
- Module.__init__(self, 'MTPT', dom_node)
- self.path = get_text(dom_node, 'path')
- self.mds_uuid = get_first_ref(dom_node, 'mds')
- self.lov_uuid = get_first_ref(dom_node, 'osc')
- self.add_module('lustre/mdc', 'mdc')
- self.add_module('lustre/llite', 'llite')
- l = lookup(self.dom_node.parentNode, self.lov_uuid)
- self.osc = VOSC(l)
-
- def prepare(self):
- self.osc.prepare()
- mdc_uuid = prepare_mdc(self.dom_node.parentNode, self.mds_uuid)
- self.info(self.path, self.mds_uuid, self.lov_uuid)
- cmd = "mount -t lustre_lite -o osc=%s,mdc=%s none %s" % \
- (self.lov_uuid, mdc_uuid, self.path)
- run("mkdir", self.path)
- ret, val = run(cmd)
- if ret:
- panic("mount failed:", self.path)
-
- def cleanup(self):
- self.info(self.path, self.mds_uuid,self.lov_uuid)
- if config.force():
- (rc, out) = run("umount -f", self.path)
- else:
- (rc, out) = run("umount", self.path)
- if rc:
- log("umount failed, cleanup will most likely not work.")
- l = lookup(self.dom_node.parentNode, self.lov_uuid)
- self.osc.cleanup()
- cleanup_mdc(self.dom_node.parentNode, self.mds_uuid)
-
- def load_module(self):
- self.osc.load_module()
- Module.load_module(self)
- def cleanup_module(self):
- Module.cleanup_module(self)
- self.osc.cleanup_module()
-
-
-# ============================================================
-# XML processing and query
-# TODO: Change query funcs to use XPath, which is muc cleaner
-
-def get_device(obd):
- list = obd.getElementsByTagName('device')
- if len(list) > 0:
- dev = list[0]
- dev.normalize();
- size = get_attr_int(dev, 'size', 0)
- return dev.firstChild.data, size
- return '', 0
-
-# Get the text content from the first matching child
-# If there is no content (or it is all whitespace), return
-# the default
-def get_text(dom_node, tag, default=""):
- list = dom_node.getElementsByTagName(tag)
- if len(list) > 0:
- dom_node = list[0]
- dom_node.normalize()
- if dom_node.firstChild:
- txt = string.strip(dom_node.firstChild.data)
- if txt:
- return txt
- return default
-
-def get_text_int(dom_node, tag, default=0):
- list = dom_node.getElementsByTagName(tag)
- n = default
- if len(list) > 0:
- dom_node = list[0]
- dom_node.normalize()
- if dom_node.firstChild:
- txt = string.strip(dom_node.firstChild.data)
- if txt:
- try:
- n = int(txt)
- except ValueError:
- panic("text value is not integer:", txt)
- return n
-
-def get_attr(dom_node, attr, default=""):
- v = dom_node.getAttribute(attr)
- if v:
- return v
- return default
-
-def get_attr_int(dom_node, attr, default=0):
- n = default
- v = dom_node.getAttribute(attr)
- if v:
- try:
- n = int(v)
- except ValueError:
- panic("attr value is not integer", v)
- return n
-
-def get_first_ref(dom_node, tag):
- """ Get the first uuidref of the type TAG. Used one only
- one is expected. Returns the uuid."""
- uuid = None
- refname = '%s_ref' % tag
- list = dom_node.getElementsByTagName(refname)
- if len(list) > 0:
- uuid = getRef(list[0])
- return uuid
-
-def get_all_refs(dom_node, tag):
- """ Get all the refs of type TAG. Returns list of uuids. """
- uuids = []
- refname = '%s_ref' % tag
- list = dom_node.getElementsByTagName(refname)
- if len(list) > 0:
- for i in list:
- uuids.append(getRef(i))
- return uuids
-
-def get_ost_net(dom_node, uuid):
- ost = lookup(dom_node, uuid)
- uuid = get_first_ref(ost, 'network')
- if not uuid:
- return None
- return lookup(dom_node, uuid)
-
-def nid2server(dom_node, nid):
- netlist = dom_node.getElementsByTagName('network')
- for net_node in netlist:
- if get_text(net_node, 'server') == nid:
- return Network(net_node)
- return None
-
-def lookup(dom_node, uuid):
- for n in dom_node.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- if getUUID(n) == uuid:
- return n
- else:
- n = lookup(n, uuid)
- if n: return n
- return None
-
-# Get name attribute of dom_node
-def getName(dom_node):
- return dom_node.getAttribute('name')
-
-def getRef(dom_node):
- return dom_node.getAttribute('uuidref')
-
-# Get name attribute of dom_node
-def getUUID(dom_node):
- return dom_node.getAttribute('uuid')
-
-# the tag name is the service type
-# fixme: this should do some checks to make sure the dom_node is a service
-def getServiceType(dom_node):
- return dom_node.nodeName
-
-#
-# determine what "level" a particular node is at.
-# the order of iniitailization is based on level.
-def getServiceLevel(dom_node):
- type = getServiceType(dom_node)
- ret=0;
- if type in ('network',):
- ret = 10
- elif type in ('device', 'ldlm'):
- ret = 20
- elif type in ('obd', 'mdd'):
- ret = 30
- elif type in ('mds','ost'):
- ret = 40
- elif type in ('mdc','osc'):
- ret = 50
- elif type in ('lov', 'lovconfig'):
- ret = 60
- elif type in ('mountpoint', 'echo_client'):
- ret = 70
-
- if ret < config.minlevel() or ret > config.maxlevel():
- ret = 0
- return ret
-
-#
-# return list of services in a profile. list is a list of tuples
-# [(level, dom_node),]
-def getServices(lustreNode, profileNode):
- list = []
- for n in profileNode.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- servNode = lookup(lustreNode, getRef(n))
- if not servNode:
- print n
- panic('service not found: ' + getRef(n))
- level = getServiceLevel(servNode)
- if level > 0:
- list.append((level, servNode))
- list.sort()
- return list
-
-def getByName(lustreNode, name, tag):
- ndList = lustreNode.getElementsByTagName(tag)
- for nd in ndList:
- if getName(nd) == name:
- return nd
- return None
-
-
-############################################################
-# MDC UUID hack -
-# FIXME: clean this mess up!
-#
-saved_mdc = {}
-def prepare_mdc(dom_node, mds_uuid):
- global saved_mdc
- mds_node = lookup(dom_node, mds_uuid);
- if not mds_node:
- panic("no mds:", mds_uuid)
- if saved_mdc.has_key(mds_uuid):
- return saved_mdc[mds_uuid]
- mdc = MDC(mds_node)
- mdc.prepare()
- saved_mdc[mds_uuid] = mdc.uuid
- return mdc.uuid
-
-def cleanup_mdc(dom_node, mds_uuid):
- global saved_mdc
- mds_node = lookup(dom_node, mds_uuid);
- if not mds_node:
- panic("no mds:", mds_uuid)
- if not saved_mdc.has_key(mds_uuid):
- mdc = MDC(mds_node)
- mdc.cleanup()
- saved_mdc[mds_uuid] = mdc.uuid
-
-
-############################################################
-# routing ("rooting")
-#
-routes = []
-local_node = []
-router_flag = 0
-
-def init_node(dom_node):
- global local_node, router_flag
- netlist = dom_node.getElementsByTagName('network')
- for dom_net in netlist:
- type = get_attr(dom_net, 'type')
- gw = get_text(dom_net, 'server')
- local_node.append((type, gw))
-
-def node_needs_router():
- return router_flag
-
-def get_routes(type, gw, dom_net):
- """ Return the routes as a list of tuples of the form:
- [(type, gw, lo, hi),]"""
- res = []
- tbl = dom_net.getElementsByTagName('route_tbl')
- for t in tbl:
- routes = t.getElementsByTagName('route')
- for r in routes:
- lo = get_attr(r, 'lo')
- hi = get_attr(r, 'hi', '')
- res.append((type, gw, lo, hi))
- return res
-
-
-def init_route_config(lustre):
- """ Scan the lustre config looking for routers. Build list of
- routes. """
- global routes, router_flag
- routes = []
- list = lustre.getElementsByTagName('node')
- for node in list:
- if get_attr(node, 'router'):
- router_flag = 1
- for (local_type, local_nid) in local_node:
- gw = None
- netlist = node.getElementsByTagName('network')
- for dom_net in netlist:
- if local_type == get_attr(dom_net, 'type'):
- gw = get_text(dom_net, 'server')
- break
- if not gw:
- continue
- for dom_net in netlist:
- if local_type != get_attr(dom_net, 'type'):
- for route in get_routes(local_type, gw, dom_net):
- routes.append(route)
-
-
-def local_net(net):
- global local_node
- for iface in local_node:
- if net.net_type == iface[0]:
- return 1
- return 0
-
-def find_route(net):
- global local_node, routes
- frm_type = local_node[0][0]
- to_type = net.net_type
- to = net.nid
- debug ('looking for route to', to_type,to)
- for r in routes:
- if r[2] == to:
- return r
- return None
-
-
-
-
-############################################################
-# lconf level logic
-# Start a service.
-def startService(dom_node, module_flag):
- type = getServiceType(dom_node)
- debug('Service:', type, getName(dom_node), getUUID(dom_node))
- # there must be a more dynamic way of doing this...
- n = None
- if type == 'ldlm':
- n = LDLM(dom_node)
- elif type == 'lov':
- n = LOV(dom_node)
- elif type == 'lovconfig':
- n = LOVConfig(dom_node)
- elif type == 'network':
- n = Network(dom_node)
- elif type == 'obd':
- n = OBD(dom_node)
- elif type == 'ost':
- n = OST(dom_node)
- elif type == 'mds':
- n = MDS(dom_node)
- elif type == 'osc':
- n = VOSC(dom_node)
- elif type == 'mdc':
- n = MDC(dom_node)
- elif type == 'mountpoint':
- n = Mountpoint(dom_node)
- elif type == 'echo_client':
- n = ECHO_CLIENT(dom_node)
- else:
- panic ("unknown service type:", type)
-
- if module_flag:
- if config.nomod():
- return
- if config.cleanup():
- n.cleanup_module()
- else:
- n.load_module()
- else:
- if config.nosetup():
- return
- if config.cleanup():
- n.cleanup()
- else:
- n.prepare()
-
-#
-# Prepare the system to run lustre using a particular profile
-# in a the configuration.
-# * load & the modules
-# * setup networking for the current node
-# * make sure partitions are in place and prepared
-# * initialize devices with lctl
-# Levels is important, and needs to be enforced.
-def startProfile(lustreNode, profileNode, module_flag):
- if not profileNode:
- panic("profile:", profile, "not found.")
- services = getServices(lustreNode, profileNode)
- if config.cleanup():
- services.reverse()
- for s in services:
- startService(s[1], module_flag)
-
-
-#
-# Load profile for
-def doHost(lustreNode, hosts):
- global routes
- dom_node = None
- for h in hosts:
- dom_node = getByName(lustreNode, h, 'node')
- if dom_node:
- break
-
- if not dom_node:
- print 'No host entry found.'
- return
-
- if not get_attr(dom_node, 'router'):
- init_node(dom_node)
- init_route_config(lustreNode)
- else:
- global router_flag
- router_flag = 1
-
- # Two step process: (1) load modules, (2) setup lustre
- # if not cleaning, load modules first.
- module_flag = not config.cleanup()
- reflist = dom_node.getElementsByTagName('profile')
- for profile in reflist:
- startProfile(lustreNode, profile, module_flag)
-
- if not config.cleanup():
- sys_set_debug_path()
- script = config.gdb_script()
- run(lctl.lctl, ' modules >', script)
- if config.gdb():
- # dump /tmp/ogdb and sleep/pause here
- log ("The GDB module script is in", script)
- time.sleep(5)
-
- module_flag = not module_flag
- for profile in reflist:
- startProfile(lustreNode, profile, module_flag)
-
-############################################################
-# Command line processing
-#
-def parse_cmdline(argv):
- short_opts = "hdnvf"
- long_opts = ["ldap", "reformat", "lustre=", "verbose", "gdb",
- "portals=", "makeldiff", "cleanup", "noexec",
- "help", "node=", "nomod", "nosetup",
- "dump=", "force", "minlevel=", "maxlevel="]
- opts = []
- args = []
- try:
- opts, args = getopt.getopt(argv, short_opts, long_opts)
- except getopt.error:
- print "invalid opt"
- usage()
-
- for o, a in opts:
- if o in ("-h", "--help"):
- usage()
- if o in ("-d","--cleanup"):
- config.cleanup(1)
- if o in ("-v", "--verbose"):
- config.verbose(1)
- if o in ("-n", "--noexec"):
- config.noexec(1)
- config.verbose(1)
- if o == "--portals":
- config.portals = a
- if o == "--lustre":
- config.lustre = a
- if o == "--reformat":
- config.reformat(1)
- if o == "--node":
- config.node(a)
- if o == "--gdb":
- config.gdb(1)
- if o == "--nomod":
- config.nomod(1)
- if o == "--nosetup":
- config.nosetup(1)
- if o == "--dump":
- config.dump_file(a)
- if o in ("-f", "--force"):
- config.force(1)
- if o in ("--minlevel",):
- config.minlevel(a)
- if o in ("--maxlevel",):
- config.maxlevel(a)
-
- return args
-
-def fetch(url):
- import urllib
- data = ""
- try:
- s = urllib.urlopen(url)
- data = s.read()
- except:
- usage()
- return data
-
-def setupModulePath(cmd):
- base = os.path.dirname(cmd)
- if os.access(base+"/Makefile", os.R_OK):
- config.src_dir(base + "/../../")
-
-def sys_set_debug_path():
- debug("debug path: ", config.debug_path())
- if config.noexec():
- return
- try:
- fp = open('/proc/sys/portals/debug_path', 'w')
- fp.write(config.debug_path())
- fp.close()
- except IOError, e:
- print e
-
-#/proc/sys/net/core/rmem_max
-#/proc/sys/net/core/wmem_max
-def sys_set_netmem_max(path, max):
- debug("setting", path, "to at least", max)
- if config.noexec():
- return
- fp = open(path)
- str = fp.readline()
- fp.close
- cur = int(str)
- if max > cur:
- fp = open(path, 'w')
- fp.write('%d\n' %(max))
- fp.close()
-
-
-def sys_make_devices():
- if not os.access('/dev/portals', os.R_OK):
- run('mknod /dev/portals c 10 240')
- if not os.access('/dev/obd', os.R_OK):
- run('mknod /dev/obd c 10 241')
-
-
-# Add dir to the global PATH, if not already there.
-def add_to_path(new_dir):
- syspath = string.split(os.environ['PATH'], ':')
- if new_dir in syspath:
- return
- os.environ['PATH'] = os.environ['PATH'] + ':' + new_dir
-
-
-DEFAULT_PATH = ('/sbin', '/usr/sbin', '/bin', '/usr/bin')
-# ensure basic elements are in the system path
-def sanitise_path():
- for dir in DEFAULT_PATH:
- add_to_path(dir)
-
-# Initialize or shutdown lustre according to a configuration file
-# * prepare the system for lustre
-# * configure devices with lctl
-# Shutdown does steps in reverse
-#
-def main():
- global TCP_ACCEPTOR, lctl, MAXTCPBUF
- host = socket.gethostname()
-
- # the PRNG is normally seeded with time(), which is not so good for starting
- # time-synchronized clusters
- input = open('/dev/urandom', 'r')
- if not input:
- print 'Unable to open /dev/urandom!'
- sys.exit(1)
- seed = input.read(32)
- input.close()
- random.seed(seed)
-
- sanitise_path()
-
- args = parse_cmdline(sys.argv[1:])
- if len(args) > 0:
- if not os.access(args[0], os.R_OK):
- print 'File not found or readable:', args[0]
- sys.exit(1)
- dom = xml.dom.minidom.parse(args[0])
- elif config.url():
- xmldata = fetch(config.url())
- dom = xml.dom.minidom.parseString(xmldata)
- else:
- usage()
-
- node_list = []
- if config.node():
- node_list.append(config.node())
- else:
- if len(host) > 0:
- node_list.append(host)
- node_list.append('localhost')
- debug("configuring for host: ", node_list)
-
- if len(host) > 0:
- config._debug_path = config._debug_path + '-' + host
- config._gdb_script = config._gdb_script + '-' + host
-
- TCP_ACCEPTOR = find_prog('acceptor')
- if not TCP_ACCEPTOR:
- if config.noexec():
- TCP_ACCEPTOR = 'acceptor'
- debug('! acceptor not found')
- else:
- panic('acceptor not found')
-
- lctl = LCTLInterface('lctl')
-
- setupModulePath(sys.argv[0])
- sys_make_devices()
- sys_set_netmem_max('/proc/sys/net/core/rmem_max', MAXTCPBUF)
- sys_set_netmem_max('/proc/sys/net/core/wmem_max', MAXTCPBUF)
- doHost(dom.documentElement, node_list)
-
-if __name__ == "__main__":
- try:
- main()
- except LconfError, e:
- print e
- except CommandError, e:
- e.dump()
- sys.exit(e.rc)
-
- if first_cleanup_error:
- sys.exit(first_cleanup_error)
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * Author: Peter J. Braam <braam@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- * Author: Robert Read <rread@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <portals/ptlctl.h>
-#include "obdctl.h"
-#include "parser.h"
-
-static int jt_quit(int argc, char **argv) {
- Parser_quit(argc, argv);
- return 0;
-}
-
-static int jt_noop(int argc, char **argv) {
- return 0;
-}
-
-static int jt_opt_ignore_errors(int argc, char **argv) {
- Parser_ignore_errors(1);
- return 0;
-}
-
-command_t cmdlist[] = {
- /* Metacommands */
- {"--device", jt_opt_device, 0,
- "run <command> after connecting to device <devno>\n"
- "--device <devno> <command [args ...]>"},
- {"--threads", jt_opt_threads, 0,
- "run <threads> separate instances of <command> on device <devno>\n"
- "--threads <threads> <verbose> <devno> <command [args ...]>"},
- {"--ignore_errors", jt_opt_ignore_errors, 0,
- "ignore errors that occur during script processing\n"
- "--ignore_errors"},
- {"ignore_errors", jt_opt_ignore_errors, 0,
- "ignore errors that occur during script processing\n"
- "ignore_errors"},
-
- /* Network configuration commands */
- {"==== network config ====", jt_noop, 0, "network config"},
- {"network", jt_ptl_network, 0, "commands that follow apply to net\n"
- "usage: network <tcp/elan/myrinet>"},
- {"connect", jt_ptl_connect, 0, "connect to a remote nid\n"
- "usage: connect [[<hostname> <port>] | <elan id>]"},
- {"disconnect", jt_ptl_disconnect, 0, "disconnect from a remote nid\n"
- "usage: disconnect <nid>"},
- {"mynid", jt_ptl_mynid, 0, "inform the socknal of the local nid. "
- "The nid defaults to hostname for tcp networks and is automatically "
- "setup for elan/myrinet networks.\n"
- "usage: mynid [nid]"},
- {"add_uuid", jt_ptl_add_uuid, 0, "associate a UUID with a nid\n"
- "usage: add_uuid <uuid> <nid>"},
- {"close_uuid", jt_ptl_close_uuid, 0, "disconnect a UUID\n"
- "usage: close_uuid <uuid>)"},
- {"del_uuid", jt_ptl_del_uuid, 0, "delete a UUID association\n"
- "usage: del_uuid <uuid>"},
- {"add_route", jt_ptl_add_route, 0,
- "add an entry to the routing table\n"
- "usage: add_route <gateway> <target> [target]"},
- {"del_route", jt_ptl_del_route, 0,
- "delete an entry from the routing table\n"
- "usage: del_route <target>"},
- {"route_list", jt_ptl_print_routes, 0, "print the routing table\n"
- "usage: route_list"},
- {"recv_mem", jt_ptl_rxmem, 0, "set socket receive buffer size, "
- "if size is omited the current size is reported.\n"
- "usage: recv_mem [size]"},
- {"send_mem", jt_ptl_txmem, 0, "set socket send buffer size, "
- "if size is omited the current size is reported.\n"
- "usage: send_mem [size]"},
- {"nagle", jt_ptl_nagle, 0, "enable/disable nagle, omiting the "
- "argument will cause the current nagle setting to be reported.\n"
- "usage: nagle [on/off]"},
-
- /* Device selection commands */
- {"=== device selection ===", jt_noop, 0, "device selection"},
- {"newdev", jt_obd_newdev, 0, "create a new device\n"
- "usage: newdev"},
-#if 0
- {"uuid2dev", jt_obd_uuid2dev, 0,
- "find device attached with <uuid> and make it the current device\n"
- "usage: uuid2dev <uuid>"},
-#endif
- {"name2dev", jt_obd_name2dev, 0,
- "find device attached with <name> and make it the current device\n"
- "usage: name2dev <name>"},
- {"device", jt_obd_device, 0, "set current device to <devno>\n"
- "usage: device <devno>"},
- {"device_list", jt_obd_list, 0, "show all devices\n"
- "usage: device_list"},
- {"lustre_build_version", jt_get_version, 0,
- "print the build version of lustre\n"
- "usage: lustre_build_version"},
-
- /* Device configuration commands */
- {"==== device config =====", jt_noop, 0, "device config"},
- {"attach", jt_obd_attach, 0,
- "set the type of the current device (with <name> and <uuid>)\n"
- "usage: attach type [name [uuid]]"},
- {"setup", jt_obd_setup, 0,
- "type specific device configuration information\n"
- "usage: setup <args...>"},
- {"cleanup", jt_obd_cleanup, 0, "cleanup previously setup device\n"
- "usage: cleanup"},
- {"detach", jt_obd_detach, 0,
- "remove driver (and name and uuid) from current device\n"
- "usage: detach"},
- {"lov_setconfig", jt_obd_lov_setconfig, 0,
- "write lov configuration to an mds device\n"
- "usage: lov_setconfig lov-uuid stripe-count stripe-size offset pattern UUID1 [UUID2 ...]"},
- {"lov_getconfig", jt_obd_lov_getconfig, 0,
- "read lov configuration from an mds device\n"
- "usage: lov_getconfig lov-uuid"},
-
- /* Device operations */
- {"=== device operations ==", jt_noop, 0, "device operations"},
- {"probe", jt_obd_connect, 0,
- "build a connection handle to a device. This command is used to "
- "suspend configuration until lctl has ensured that the mds and osc "
- "services are available. This is to avoid mount failures in a "
- "rebooting cluster.\n"
- "usage: probe [timeout]"},
- {"close", jt_obd_disconnect, 0,
- "close the connection handle\n"
- "usage: close"},
- {"getattr", jt_obd_getattr, 0,
- "get attribute for OST object <objid>\n"
- "usage: getattr <objid>"},
- {"setattr", jt_obd_setattr, 0,
- "set mode attribute for OST object <objid>\n"
- "usage: setattr <objid> <mode>"},
- {"create", jt_obd_create, 0,
- "create <num> OST objects (with <mode>)\n"
- "usage: create [num [mode [verbose]]]"},
- {"destroy", jt_obd_destroy, 0,
- "destroy OST object <objid> [num [verbose]]\n"
- "usage: destroy <num> objects, starting at objid <objid>"},
- {"test_getattr", jt_obd_test_getattr, 0,
- "do <num> getattrs (on OST object <objid> (objid+1 on each thread))\n"
- "usage: test_getattr <num> [verbose [[t]objid]]"},
- {"test_brw", jt_obd_test_brw, 0,
- "do <num> bulk read/writes (<npages> per I/O, on OST object <objid>)\n"
- "usage: test_brw [t]<num> [write [verbose [npages [[t]objid]]]]"},
- {"test_ldlm", jt_obd_test_ldlm, 0,
- "perform lock manager test\n"
- "usage: test_ldlm"},
- {"ldlm_regress_start", jt_obd_ldlm_regress_start, 0,
- "start lock manager stress test\n"
- "usage: ldlm_regress_start [numthreads [refheld [numres [numext]]]]"},
- {"ldlm_regress_stop", jt_obd_ldlm_regress_stop, 0,
- "stop lock manager stress test (no args)\n"},
- {"dump_ldlm", jt_obd_dump_ldlm, 0,
- "dump all lock manager state (no args)"},
- {"lov_set_osc_active", jt_obd_lov_set_osc_active, 0,
- "(de)activate an OSC in a LOV\n"
- "usage: lov_set_osc_active <OSC UUID> <1|0 (active|inactive)>"},
- {"newconn", jt_obd_newconn, 0, "newconn <olduuid> [newuuid]"},
- {"failconn", jt_obd_failconn, 0, "failconn <uuid>"},
-
- /* Debug commands */
- {"======== debug =========", jt_noop, 0, "debug"},
- {"debug_kernel", jt_dbg_debug_kernel, 0,
- "get debug buffer and dump to a file"
- "usage: debug_kernel [file] [raw]"},
- {"debug_file", jt_dbg_debug_file, 0,
- "read debug buffer from input and dump to output"
- "usage: debug_file <input> [output] [raw]"},
- {"clear", jt_dbg_clear_debug_buf, 0, "clear kernel debug buffer\n"
- "usage: clear"},
- {"mark", jt_dbg_mark_debug_buf, 0,"insert marker text in kernel debug buffer\n"
- "usage: mark <text>"},
- {"filter", jt_dbg_filter, 0, "filter message type\n"
- "usage: filter <subsystem id/debug mask>"},
- {"show", jt_dbg_show, 0, "show message type\n"
- "usage: show <subsystem id/debug mask>"},
- {"debug_list", jt_dbg_list, 0, "list subsystem and debug types\n"
- "usage: debug_list <subs/types>"},
- {"modules", jt_dbg_modules, 0,
- "provide gdb-friendly module information\n"
- "usage: modules <path>"},
- {"panic", jt_dbg_panic, 0, "force the kernel to panic\n"
- "usage: panic"},
-
- /* User interface commands */
- {"======= control ========", jt_noop, 0, "control commands"},
- {"help", Parser_help, 0, "help"},
- {"exit", jt_quit, 0, "quit"},
- {"quit", jt_quit, 0, "quit"},
- { 0, 0, 0, NULL }
-};
-
-
-
-int main(int argc, char **argv)
-{
- int rc;
-
- setlinebuf(stdout);
-
- ptl_initialize(argc, argv);
- if (obd_initialize(argc, argv) < 0)
- exit(2);
- if (dbg_initialize(argc, argv) < 0)
- exit(3);
-
- if (argc > 1) {
- rc = Parser_execarg(argc - 1, argv + 1, cmdlist);
- } else {
- Parser_init("lctl > ", cmdlist);
- rc = Parser_commands();
- }
-
- obd_cleanup(argc, argv);
- return rc;
-}
-
+++ /dev/null
-#define _XOPEN_SOURCE 500
-
-#include <stdio.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <libgen.h>
-#include <ftw.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#define printk printf
-#include <linux/lustre_lib.h>
-#include <linux/lustre_lite.h>
-#include <linux/obd_lov.h>
-
-#warning Max obds per lov currently hardcoded to 1000 in lov/lov_obd.c
-#define MAX_LOV_UUID_COUNT 1000
-#define OBD_NOT_FOUND ((__u32)-1)
-
-char * cmd;
-struct option longOpts[] = {
- {"help", 0, 0, 'h'},
- {"obd", 1, 0, 'o'},
- {"query", 0, 0, 'o'},
- {"verbose", 0, 0, 'v'},
- {0, 0, 0, 0}
- };
-int query;
-int verbose;
-char * shortOpts = "ho:qv";
-char * usageMsg = "[ --obd <obd uuid> | --query ] <dir|file> ...";
-
-int max_ost_count = MAX_LOV_UUID_COUNT;
-obd_uuid_t * obduuid;
-__u32 obdcount;
-__u32 obdindex;
-char * buf;
-int buflen;
-struct obd_ioctl_data data;
-struct lov_desc desc;
-obd_uuid_t * uuids;
-int uuidslen;
-int cfglen;
-struct lov_mds_md *lmm;
-int lmmlen;
-
-void init();
-void usage(FILE *stream);
-void errMsg(char *fmt, ...);
-void processPath(char *path);
-int processFile(
- const char *path,
- const struct stat *sp,
- int flag,
- struct FTW *ftwp
- );
-__u32 getobdindex(const char *path);
-
-int
-main (int argc, char **argv) {
- int c;
-
- cmd = basename(argv[0]);
-
- while ((c = getopt_long(argc, argv, shortOpts, longOpts, NULL)) != -1) {
- switch (c) {
- case 'o':
- if (obduuid) {
- errMsg("obd '%s' already specified: '%s'.",
- obduuid, optarg);
- exit(1);
- }
-
- obduuid = (obd_uuid_t *)optarg;
- break;
- case 'h':
- usage(stdout);
- exit(0);
- case 'q':
- query++;
- break;
- case 'v':
- verbose++;
- break;
- case '?':
- usage(stderr);
- exit(1);
- default:
- errMsg("Internal error. Valid '%s' unrecognized.",
- argv[optind - 1]);
- usage(stderr);
- exit(1);
- }
- }
-
- if (optind >= argc) {
- usage(stderr);
- exit(1);
- }
-
- if (obduuid == NULL)
- query++;
-
- init();
-
- do {
- processPath(argv[optind]);
- } while (++optind < argc);
-
- exit (0);
-}
-
-void
-init()
-{
- int datalen, desclen;
-
- datalen = size_round(sizeof(data));
- desclen = size_round(sizeof(desc));
- uuidslen = size_round(max_ost_count * sizeof(*uuids));
- cfglen = datalen + desclen + uuidslen;
- lmmlen = lov_mds_md_size(max_ost_count);
- if (cfglen > lmmlen)
- buflen = cfglen;
- else
- buflen = lmmlen;
-
-#warning max ioctl buffer size currently hardcoded to 8192
- if (buflen > 8192) {
- int nuuids, remaining, nluoinfos;
-
- buflen = 8192;
- nuuids = (buflen - datalen - desclen) / sizeof(*uuids);
- uuidslen = size_round(nuuids * sizeof(*uuids));
- remaining = nuuids * sizeof(*uuids);
- if (uuidslen > remaining)
- nuuids--;
- nluoinfos = (buflen - sizeof(*lmm)) / sizeof(*lmm->lmm_objects);
- if (nuuids > nluoinfos)
- max_ost_count = nluoinfos;
- else
- max_ost_count = nuuids;
-
- cfglen = datalen + desclen + uuidslen;
- lmmlen = lov_mds_md_size(max_ost_count);
- }
-
- if ((buf = malloc(buflen)) == NULL) {
- errMsg("Unable to allocate %d bytes of memory for ioctl's.",
- buflen);
- exit(1);
- }
-
- lmm = (struct lov_mds_md *)buf;
- uuids = (obd_uuid_t *)buf;
-}
-
-void
-usage(FILE *stream)
-{
- fprintf(stream, "usage: %s %s\n", cmd, usageMsg);
-}
-
-void
-errMsg(char *fmt, ...)
-{
- va_list args;
-
- fprintf(stderr, "%s: ", cmd);
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- fprintf(stderr, "\n");
-}
-
-void
-processPath(char *path)
-{
- obdindex = OBD_NOT_FOUND;
- nftw((const char *)path, processFile, 128, FTW_PHYS|FTW_MOUNT);
-}
-
-int
-processFile(const char *path, const struct stat *sp, int flag, struct FTW *ftwp)
-{
- int fd;
- int count;
- int rc;
- int i;
-
- if (flag != FTW_F)
- return 0;
-
- if ((obdcount == 0) && (getobdindex(path) == OBD_NOT_FOUND)) {
- /* terminate nftw walking this tree */
- return(1);
- }
-
- if ((fd = open(path, O_RDONLY)) < 0) {
- errMsg("open \"%.20s\" failed.", path);
- perror("open");
- exit(1);
- }
-
- memset((void *)buf, 0, buflen);
- lmm->lmm_magic = LOV_MAGIC;
- lmm->lmm_ost_count = max_ost_count;
-
- if ((rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, (void *)lmm)) < 0) {
- errMsg("LL_IOC_LOV_GETSTRIPE ioctl failed.");
- perror("ioctl");
- exit(1);
- }
-
- close(fd);
-
- if (query || verbose)
- printf("\n%s:\n", path);
-
- if (verbose) {
- printf("lmm_magic: 0x%x\n", lmm->lmm_magic);
- printf("lmm_object_id: "LPX64"\n", lmm->lmm_object_id);
- printf("lmm_stripe_offset: %d\n", lmm->lmm_stripe_offset);
- printf("lmm_stripe_count: %d\n", lmm->lmm_stripe_count);
- printf("lmm_ost_count: %d\n", lmm->lmm_ost_count);
- printf("lmm_stripe_pattern: %d\n", lmm->lmm_stripe_pattern);
- }
-
- count = lmm->lmm_ost_count;
-
- if (query || verbose) {
- struct lov_object_id *loi;
- __u64 oid;
-
- loi = lmm->lmm_objects;
-
- printf("obdidx\tobjid\n");
-
- for (i = 0; i < count; i++, loi++)
- if ((oid = loi->l_object_id))
- printf("%6d\t%5lld\n", i, (long long)oid);
-
- if (query)
- return(0);
- }
-
- if (lmm->lmm_objects[obdindex].l_object_id)
- printf("%s\n", path);
-
- return(0);
-}
-
-__u32
-getobdindex(const char *path)
-{
- obd_uuid_t *uuidp;
- int fd;
- int rc;
- int i;
-
- if ((fd = open(path, O_RDONLY)) < 0) {
- errMsg("open \"%.20s\" failed.", path);
- perror("open");
- exit(1);
- }
-
- data.ioc_inllen1 = sizeof(desc);
- data.ioc_inlbuf1 = (char *)&desc;
- data.ioc_inllen2 = uuidslen;
- data.ioc_inlbuf2 = (char *)uuids;
- data.ioc_inllen3 = 0;
-
- memset(&desc, 0, sizeof(desc));
- desc.ld_tgt_count = max_ost_count;
-
- if (obd_ioctl_pack(&data, &buf, buflen)) {
- errMsg("internal buffering error.");
- exit(1);
- }
-
- rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
- if (rc) {
- errMsg("OBD_IOC_LOV_GET_CONFIG ioctl failed: %d.", errno);
- perror("ioctl");
- exit(1);
- }
-
- if (obd_ioctl_unpack(&data, buf, buflen)) {
- errMsg("Invalid reply from ioctl.");
- exit(1);
- }
-
- close(fd);
-
- obdcount = desc.ld_tgt_count;
-
- if (query) {
- printf("OBDS:\n");
- for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++)
- printf("%4d: %s\n", i, (char *)uuidp);
-
- return(0);
- }
-
- for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
- rc = strncmp((const char *)obduuid, (const char *)uuidp,
- sizeof(*uuidp));
- if (rc == 0) {
- obdindex = i;
- break;
- }
- }
-
- if (obdindex == OBD_NOT_FOUND) {
- errMsg("obd UUID '%s' not found.", obduuid);
- return(OBD_NOT_FOUND);
- }
-
- return(0);
-}
+++ /dev/null
-#!/usr/bin/perl
-
-use Getopt::Long;
-use Term::ANSIColor;
-
-GetOptions("pid=i" => \$pid,
- "trace!" => \$trace,
- "silent!" => \$silent,
- "rpctrace!" => \$rpctrace,
- "nodlm!" => \$nodlm,
- "noclass!" => \$noclass,
- "nonet!" => \$nonet);
-
-print "pid: $pid, nodlm $nodlm nonet $nonet trace $trace\n";
-
-
-$subsys->{UNDEFINED} = 0;
-$subsys->{MDC} = 1;
-$subsys->{MDS} = 2;
-$subsys->{OSC} = 3;
-$subsys->{OST} = 4;
-$subsys->{CLASS} = 5;
-$subsys->{OBDFS} = 6;
-$subsys->{LLITE} = 7;
-$subsys->{RPC} = 8;
-$subsys->{EXT2OBD} = 9;
-$subsys->{PORTALS} = 10;
-$subsys->{SOCKNAL} = 11;
-$subsys->{QSWNAL} = 12;
-$subsys->{PINGER} = 13;
-$subsys->{FILTER} = 14;
-$subsys->{TRACE} = 15; # obdtrace, not to be confused with D_TRACE */
-$subsys->{ECHO} = 16;
-$subsys->{LDLM} = 17;
-$subsys->{LOV} = 18;
-$subsys->{GMNAL} = 19;
-$subsys->{PTLROUTER} = 20;
-
-
-$masks->{TRACE} = 1 << 0; # /* ENTRY/EXIT markers */
-$masks->{INODE} = 1 << 1; #
-$masks->{SUPER} = 1 << 2; #
-$masks->{EXT2} = 1 << 3; # /* anything from ext2_debug */
-$masks->{MALLOC} = 1 << 4; # /* print malloc, free information */
-$masks->{CACHE} = 1 << 5; # /* cache-related items */
-$masks->{INFO} = 1 << 6; # /* general information */
-$masks->{IOCTL} = 1 << 7; # /* ioctl related information */
-$masks->{BLOCKS} = 1 << 8; # /* ext2 block allocation */
-$masks->{NET} = 1 << 9; # /* network communications */
-$masks->{WARNING} = 1 << 10; #
-$masks->{BUFFS} = 1 << 11; #
-$masks->{OTHER} = 1 << 12; #
-$masks->{DENTRY} = 1 << 13; #
-$masks->{PORTALS} = 1 << 14; # /* ENTRY/EXIT markers */
-$masks->{PAGE} = 1 << 15; # /* bulk page handling */
-$masks->{DLMTRACE} = 1 << 16; #
-$masks->{ERROR} = 1 << 17; # /* CERROR} = ...) == CDEBUG} = D_ERROR, ...) */
-$masks->{EMERG} = 1 << 18; # /* CEMERG} = ...) == CDEBUG} = D_EMERG, ...) */
-$masks->{HA} = 1 << 19; # /* recovery and failover */
-$masks->{RPCTRACE} = 1 << 19; # /* recovery and failover */
-
-sub extractpid
-{
- $line = shift;
-# print "$_\n";
- if ($line =~ m/\(\) ([0-9]*)\+[0-9]*\):/) {
- return $1;
- }
- if ($line =~ m/\(\) ([0-9]*) | [0-9]*\+[0-9]*\):/) {
- return $1;
- }
-}
-
-sub entering
-{
- $_ = shift;
- $entering = /Process entered/;
-}
-
-sub leaving
-{
- $_ = shift;
- $entering = /Process leaving/;
-}
-
-sub getsubsys
-{
- my ($subsys, $mask) = split ":";
- return hex($subsys);
-}
-
-sub getmask
-{
- my ($subsys, $mask) = split ":";
- return hex($mask);
-}
-
-sub setcolor
-{
- my $linemask = shift;
- if ($linemask == $masks->{TRACE}) {
- print color("yellow on_black");
- }
- if ($linemask == $masks->{DLMTRACE}) {
- print color("magenta on_black");
- }
- if ($linemask == $masks->{DLM}) {
- print color("magenta on_black");
- }
- if ($linemask == $masks->{DENTRY}) {
- print color("red on_black");
- }
-}
-
-sub study_lock
-{
- $_ = shift;
- my $rc;
-
- $rc = /completion callback handler START ns: (.*) lock: (.*) lrc: (.*) mode/;
- if ($rc) {
- $completion_callbacks{$1}->{$2} = $3;
-# print color("white");
-# print "---CP CB START: $1 $2 $3\n";
-# print color("reset");
- }
- $rc = /callback handler finished.* ns: (.*) lock: (.*) lrc: (.*) mode/;
- if ($rc) {
-# print color("white");
-# print "---CP CB END: $1 $2 $3 deleting $completion_callbacks{$1}->{$2}\n";
-# print color("reset");
- delete $completion_callbacks{$1}->{$2};
- }
-
- if ($rc) {
- $rc = /client blocking AST callback handler START ns: (.*) lock: (.*) lrc: (.*) mode/;
- $blocking_callbacks{$1}->{$2} = $3;
-# print color("white");
-# print "---BL CB START: $1 $2\n";
-# print color("reset");
- }
- $rc = /client blocking callback handler END ns: (.*) lock: (.*) lrc: (.*) mode/;
- if ($rc) {
-# print color("white");
-# print "---BL CB END: $1 $2 $3 deleting $blocking_callbacks{$1}->{$2}\n";
-# print color("reset");
- delete $blocking_callbacks{$1}->{$2};
- }
-
- $rc = /ldlm_lock_addref.*ns: (.*) lock: (.*) lrc: (.*) mode/;
-# print color("white");
-# print "------>addref ns: $1 lock: $2 lrc: $3\n" if ($rc);
-# print color("reset");
- $locks{$1}->{$2} = {$3} if ($rc);
- $rc = /ldlm_lock_decref.*ns: (.*) lock: (.*) lrc: (.*) mode/;
-# print color("white");
-# print "------>decref ns: $1 lock: $2 lrc: $3\n" if ($rc);
-# print color("reset");
- $locks{$1}->{$2} = {$3} if ($rc);
-}
-
-sub hanging_locks
-{
- my $found;
- my $ns;
-
- foreach (keys %completion_callbacks) {
- $ns = $_;
- $found = 0;
- foreach (keys %{$completion_callbacks{$ns}}) {
- if (!$found) {
- print "Unfinished completions in ns $ns: \n";
- $found =1;
- }
- print " lock: $_ lrc: $completion_callbacks{$ns}->{$_}\n";
- }
- }
- foreach (keys %blocking_callbacks) {
- $ns = $_;
- $found = 0;
- foreach (keys %{$blocking_callbacks{$ns}}) {
- if (!$found) {
- print "Unfinished blocking in ns $ns: \n";
- $found =1;
- }
- printf(" lock: $_ lrc: %s\n", $blocking_callbacks{$ns}->{$_});
- }
- }
-
-}
-
-sub study_intent
-{
- $_ = shift;
- my $rc;
-
- $rc = /D_IT UP dentry (.*) fsdata/;
- delete $it{$1} if ($rc);
- $rc = /D_IT DOWN dentry (.*) fsdata/;
- $it{$1} = "yes" if ($rc);
-}
-
-sub unmatched_intents {
- my $found;
- foreach (keys %it) {
- if (!$found) {
- print "Unmatched intents: \n";
- $found =1;
- }
- print " $_\n";
- }
-}
-
-while (<STDIN>) {
- $linepid = extractpid($_);
- $linemask = getmask($_);
- $linesubsys = getsubsys($_);
-
-# printf "---> mask %x subsys %x\n", $linemask, $linesubsys;
-
- if (leaving($_)) {
- chop $prefix->{$linepid};
- chop $prefix->{$linepid};
- }
-
- if ($linemask == $masks->{DENTRY}) {
- study_intent($_);
- }
- if ($linemask == $masks->{DLMTRACE}) {
- study_lock($_);
- }
-
- if ( !$pid || $linepid == $pid) {
- next if ($rpctrace && $linemask != $masks->{RPCTRACE});
- next if ($trace && $linemask != $masks->{TRACE});
-
-
- next if ($nodlm &&
- ( $linesubsys == $subsys->{LDLM}));
- next if ($noclass &&
- ( $linesubsys == $subsys->{CLASS}));
-
- next if ($nonet &&
- ( $linesubsys == $subsys->{RPC} ||
- $linesubsys == $subsys->{NET} ||
- $linesubsys == $subsys->{PORTALS} ||
- $linesubsys == $subsys->{SOCKNAL} ||
- $linesubsys == $subsys->{QSWNAL} ||
- $linesubsys == $subsys->{GMNAL}));
-
-
-# printf "sub/mask: %s - %s\n", getsubsys($_), getmask($_);
- if (!$silent) {
- setcolor($linemask);
- printf("%s%s", $prefix->{$linepid}, $_);
- print color("reset");
- }
- # last if $count++ > 100;
- }
- if (entering($_)) {
- $prefix->{$linepid} .= ' ';
- }
-}
-
-
-unmatched_intents();
-hanging_locks();
-# printf "argv %s pid %d\n", $ARGV[0], extractpid($ARGV[0]);
+++ /dev/null
-#!/usr/bin/env python
-# Copyright (C) 2002 Cluster File Systems, Inc.
-# Author: Robert Read <rread@clusterfs.com>
-
-# This file is part of Lustre, http://www.lustre.org.
-#
-# Lustre is free software; you can redistribute it and/or
-# modify it under the terms of version 2 of the GNU General Public
-# License as published by the Free Software Foundation.
-#
-# Lustre 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 Lustre; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-"""
-lmc - lustre configurtion data manager
-
- Basic plan for lmc usage:
-# create nodes
-./lmc --output config.xml --node server --net server1 tcp
-./lmc --merge config.xml --node client --net client1 tcp
-./lmc --merge config.xml --node client --route gw lo [hi]
-./lmc --merge config.xml --router --node gw1 --net gw1 tcp
-./lmc --merge config.xml --node gw1 --net 1 elan
-
-./lmc --merge config.xml --route elan 1 1 100
-./lmc --merge config.xml --route tcp gw1 ba1
-
-
-
-# configure server
-./lmc --merge config.xml --node server --mds mds1 /tmp/mds1 50000
-
-# create lov
-./lmc --merge config.xml --lov lov1 mds1 65536 0 0
-./lmc --merge config.xml --node server --lov lov1 --ost /tmp/ost1 100000
-./lmc --merge config.xml --node server --lov lov1 --ost /tmp/ost2 100000
-
-# create client config
-./lmc --merge config.xml --node client --mtpt /mnt/lustre mds1 lov1
-
-"""
-
-import sys, os, getopt, string
-import xml.dom.minidom
-from xml.dom.ext import PrettyPrint
-
-
-DEFAULT_PORT = 988 # XXX What is the right default acceptor port to use?
-
-def usage():
- print """usage: lmc [--node --ost | --mtpt | --lov] args
-Commands:
---node node_name
- Node_name by itself it will create a new node. If the --router
- option is used when creating a new node, then that node will also
- be configured as a router. When used with other commands it
- specifies the node to modify.
-
---net hostname nettype [port, recv_buf, send_buf]
- Nettype is either tcp, toe, elan, or gm.
- Requires --node
-
---route net gw lo [hi]
- This command is used to create routes. NET is the
- network type this route will be used on. The GW is an address of
- one of the local interfaces. LO and HI represent a range of
- addresses that can be reached through the gateway. If HI is not
- set, then a route to the specific host in LO is created.
-
---mds device [size]
- Create a MDS using the device
- Requires --node
-
---lov lov_name [mds_name stripe_sz sub_stripe_count pattern]
- Creates a logical volume
- When used with other commands, it specifics the lov to modify
-
---ost device [size]
- Creates an OBD/OST/OSC configuration triplet for a new device.
- When used on "host", the device will be initialized and the OST
- will be enabled. On client nodes, the OSC will be avaiable.
- Requires --node
- Optional --obduuid Specifies the UUID used for the obd.
- If --lov lov_name is used, this device is added to lov.
-
---mtpt /mnt/point mds_name lov_name|osc_name
- Creates a client mount point.
- Requires --node
-
-Options:
---merge="xml file" Add the new objects to an existing file
---format Format the partitions if unformated
- NB: The autoformat option has been disabled until a safe
- method is implemented to determine if a block device has a
- filesystem.
---reformat Reformat partitions (this should be an lconf arg,
- I think)
---obdtype="obdtype" Specifiy obdtype: valid ones are obdecho and obdfilter.
- This is only useful for the --ost command.
- The device parameters are ignored for the obdecho type.
-"""
- sys.exit(1)
-
-def error(*args):
- msg = string.join(map(str,args))
- print "Error: ", msg
- sys.exit(1)
-
-def warning(*args):
- msg = string.join(map(str,args))
- print "Warning: ", msg
-
-#
-# manage names and uuids
-# need to initialize this by walking tree to ensure
-# no duplicate names or uuids are created.
-# this are just place holders for now.
-# consider changing this to be like OBD-dev-host
-def new_name(base):
- ctr = 2
- ret = base
- while names.has_key(ret):
- ret = "%s_%d" % (base, ctr)
- ctr = 1 + ctr
- names[ret] = 1
- return ret
-
-def new_uuid(name):
- return "%s_UUID" % (name)
-
-ldlm_name = 'ldlm'
-ldlm_uuid = 'ldlm_UUID'
-def new_lustre(dom):
- """Create a new empty lustre document"""
- # adding ldlm here is a bit of a hack, but one is enough.
- str = """<lustre>
- <ldlm name="%s" uuid="%s"/>
- </lustre>""" % (ldlm_name, ldlm_uuid)
- return dom.parseString(str)
-
-names = {}
-uuids = {}
-
-def init_names(doc):
- """initialize auto-name generation tables"""
- global names, uuids
- # get all elements that contain a name attribute
- for n in doc.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- if getName(n):
- names[getName(n)] = 1
- uuids[getUUID(n)] = 1
- init_names(n)
-
-def get_format_flag(options):
- if options.has_key('format'):
- if options['format']:
- return 'yes'
- return 'no'
-
-############################################################
-# Build config objects using DOM
-#
-class GenConfig:
- doc = None
- dom = None
- def __init__(self, doc):
- self.doc = doc
-
- def ref(self, type, uuid):
- """ generate <[type]_ref uuidref="[uuid]"/> """
- tag = "%s_ref" % (type)
- ref = self.doc.createElement(tag)
- ref.setAttribute("uuidref", uuid)
- return ref
-
- def newService(self, tag, name, uuid):
- """ create a new service elmement, which requires name and uuid attributes """
- new = self.doc.createElement(tag)
- new.setAttribute("name", name);
- new.setAttribute("uuid", uuid);
- return new
-
- def addText(self, node, str):
- txt = self.doc.createTextNode(str)
- node.appendChild(txt)
-
- def addElement(self, node, tag, str=None):
- """ create a new element and add it as a child to node. If str is passed,
- a text node is created for the new element"""
- new = self.doc.createElement(tag)
- if str:
- self.addText(new, str)
- node.appendChild(new)
- return new
-
- def network(self, name, uuid, hostname, net, port=0, tcpbuf=0):
- """create <network> node"""
- network = self.newService("network", name, uuid)
- network.setAttribute("type", net);
- self.addElement(network, "server", hostname)
- if port:
- self.addElement(network, "port", "%d" %(port))
- if tcpbuf:
- self.addElement(network, "send_mem", "%d" %(tcpbuf))
- self.addElement(network, "recv_mem", "%d" %(tcpbuf))
-
- return network
-
- def route(self, net_type, gw, lo, hi):
- """ create one entry for the route table """
- ref = self.doc.createElement('route')
- ref.setAttribute("type", net_type)
- ref.setAttribute("gw", gw)
- ref.setAttribute("lo", lo)
- if hi:
- ref.setAttribute("hi", hi)
- return ref
-
- def node(self, name, uuid):
- """ create a host """
- node = self.newService("node", name, uuid)
- self.addElement(node, 'profile')
- return node
-
- def ldlm(self, name, uuid):
- """ create a ldlm """
- ldlm = self.newService("ldlm", name, uuid)
- return ldlm
-
- def obd(self, name, uuid, fs, obdtype, devname, format, dev_size=0):
- obd = self.newService("obd", name, uuid)
- obd.setAttribute('type', obdtype)
- if fs:
- self.addElement(obd, "fstype", fs)
- if devname:
- dev = self.addElement(obd, "device", devname)
- if (dev_size):
- dev.setAttribute("size", "%s" % (dev_size))
- self.addElement(obd, "autoformat", format)
- return obd
-
- def osc(self, name, uuid, obd_uuid, net_uuid):
- osc = self.newService("osc", name, uuid)
- osc.appendChild(self.ref("ost", net_uuid))
- osc.appendChild(self.ref("obd", obd_uuid))
- return osc
-
- def ost(self, name, uuid, obd_uuid, net_uuid):
- ost = self.newService("ost", name, uuid)
- ost.appendChild(self.ref("network", net_uuid))
- ost.appendChild(self.ref("obd", obd_uuid))
- return ost
-
- def lov(self, name, uuid, mds_uuid, stripe_sz, stripe_count, pattern):
- lov = self.newService("lov", name, uuid)
- lov.appendChild(self.ref("mds", mds_uuid))
- devs = self.addElement(lov, "devices" )
- devs.setAttribute("stripesize", stripe_sz)
- devs.setAttribute("stripecount", stripe_count)
- devs.setAttribute("pattern", pattern)
- return lov
-
- def lovconfig(self, name, uuid, lov_uuid):
- lovconfig = self.newService("lovconfig", name, uuid)
- lovconfig.appendChild(self.ref("lov", lov_uuid))
- return lovconfig
-
- def mds(self, name, uuid, fs, devname, format, net_uuid, node_uuid,
- failover_uuid = "", dev_size=0 ):
- mds = self.newService("mds", name, uuid)
- self.addElement(mds, "fstype", fs)
- dev = self.addElement(mds, "device", devname)
- if dev_size:
- dev.setAttribute("size", "%s" % (dev_size))
- self.addElement(mds, "autoformat", format)
- mds.appendChild(self.ref("network", net_uuid))
- mds.appendChild(self.ref("node", node_uuid))
- if failover_uuid:
- mds.appendChild(self.ref("failover", failover_uuid))
- return mds
-
- def mountpoint(self, name, uuid, mds_uuid, osc_uuid, path):
- mtpt = self.newService("mountpoint", name, uuid)
- mtpt.appendChild(self.ref("mds", mds_uuid))
- mtpt.appendChild(self.ref("osc", osc_uuid))
- self.addElement(mtpt, "path", path)
- return mtpt
-
- def echo_client(self, name, uuid, osc_uuid):
- ec = self.newService("echo_client", name, uuid)
- ec.appendChild(self.ref("osc", osc_uuid))
- return ec
-
-############################################################
-# Utilities to query a DOM tree
-# Using this functions we can treat use config information
-# directly as a database.
-def getName(n):
- return n.getAttribute('name')
-
-def getUUID(node):
- return node.getAttribute('uuid')
-
-
-def findByName(lustre, name, tag = ""):
- for n in lustre.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- if tag and n.nodeName != tag:
- continue
- if getName(n) == name:
- return n
- else:
- n = findByName(n, name)
- if n: return n
- return None
-
-
-def lookup(node, uuid):
- for n in node.childNodes:
- if n.nodeType == n.ELEMENT_NODE:
- if getUUID(n) == uuid:
- return n
- else:
- n = lookup(n, uuid)
- if n: return n
- return None
-
-
-def mds2node(lustre, mds_name):
- """ Find the node a MDS is configured on """
- mds = findByName(lustre, mds_name, 'mds')
- ref = mds.getElementsByTagName('node_ref')
- if not ref:
- error("mds2node:", "no node_ref found for", '"'+mds_name+'"')
- node_uuid = ref[0].getAttribute('uuidref')
- node = lookup(lustre, node_uuid)
- if not node:
- error('mds2node:', "no node found for :", '"'+mds_name+'"')
- return node
-
-
-def name2uuid(lustre, name, tag="", fatal=1):
- ret = findByName(lustre, name, tag)
- if not ret:
- if fatal:
- error('name2uuid:', '"'+name+'"', tag, 'element not found.')
- else:
- return ""
- return getUUID(ret)
-
-
-# XXX: assumes only one network element per node. will fix this
-# as soon as support for routers is added
-def get_net_uuid(lustre, node_name):
- """ get a network uuid for a node_name """
- node = findByName(lustre, node_name, "node")
- if not node:
- error ('get_net_uuid:', '"'+node_name+'"', "node element not found.")
- net = node.getElementsByTagName('network')
- if net:
- return getUUID(net[0])
- return None
-
-
-def lov_add_osc(gen, lov, osc_uuid):
- devs = lov.getElementsByTagName('devices')
- if len(devs) == 1:
- devs[0].appendChild(gen.ref("osc", osc_uuid))
- else:
- error("No devices element found for LOV:", lov)
-
-
-def node_add_profile(gen, node, ref, uuid):
- ret = node.getElementsByTagName('profile')
- if not ret:
- error('node has no profile:', node)
- ret[0].appendChild(gen.ref(ref, uuid))
-
-def get_attr(dom_node, attr, default=""):
- v = dom_node.getAttribute(attr)
- if v:
- return v
- return default
-
-############################################################
-# Top level commands
-#
-def do_add_node(gen, lustre, options, node_name):
- uuid = new_uuid(node_name)
- node = gen.node(node_name, uuid)
- node_add_profile(gen, node, 'ldlm', ldlm_uuid)
- if options.has_key('router'):
- node.setAttribute('router', '1')
- lustre.appendChild(node)
- return node
-
-
-def add_node(gen, lustre, options, args):
- """ create a node with a network config """
- if len(args) > 1:
- usage()
-
- node_name = options['node']
-
- ret = findByName(lustre, node_name, "node")
- if ret:
- print "Node:", node_name, "exists."
- return
- do_add_node(gen, lustre, options, node_name)
-
-
-def add_net(gen, lustre, options, args):
- """ create a node with a network config """
- if len(args) < 2:
- usage()
-
- node_name = options['node']
- nid = args[0]
- net_type = args[1]
- port = 0
- tcpbuf = 0
-
- if net_type in ('tcp', 'toe'):
- if len(args) > 2:
- port = int(args[2])
- else:
- port = DEFAULT_PORT
- if options.has_key('tcpbuf'):
- tcpbuf = int(options['tcpbuf'])
- elif net_type in ('elan', 'gm'):
- port = 0
- else:
- print "Unknown net_type: ", net_type
- sys.exit(2)
-
- ret = findByName(lustre, node_name, "node")
- if not ret:
- node = do_add_node(gen, lustre, options, node_name)
- else:
- node = ret
- net_name = new_name('NET_'+ node_name +'_'+ net_type)
- net_uuid = new_uuid(net_name)
- node.appendChild(gen.network(net_name, net_uuid, nid, net_type, port, tcpbuf))
- node_add_profile(gen, node, "network", net_uuid)
-
-
-def add_route(gen, lustre, options, args):
- """ create a node with a network config """
- if len(args) < 3:
- usage()
-
- node_name = options['node']
- net_type= args[0]
- gw = args[1]
- lo = args[2]
- hi = ''
-
- if len(args) > 3:
- hi = args[3]
-
- node = findByName(lustre, node_name, "node")
- if not node:
- error (node_name, " not found.")
-
- netlist = node.getElementsByTagName('network')
- net = netlist[0]
- rlist = net.getElementsByTagName('route_tbl')
- if len(rlist) > 0:
- rtbl = rlist[0]
- else:
- rtbl = gen.addElement(net, 'route_tbl')
- rtbl.appendChild(gen.route(net_type, gw, lo, hi))
-
-
-def add_mds(gen, lustre, options, args):
- fstype = 'extN'
-
- if len(args) < 1:
- usage()
-
- if options.has_key('node'):
- node_name = options['node']
- else:
- error("--mds requires a --node argument")
-
- if options.has_key('fstype'):
- fstype = options['fstype']
-
- mds_name = new_name(options['mds'])
- if mds_name != options['mds']:
- warning("name:", options['mds'], "already used. using:", mds_name)
- devname = args[0]
- if len(args) > 1:
- size = args[1]
- else:
- size = 0
-
- mds_uuid = new_uuid(mds_name)
-
- node_uuid = name2uuid(lustre, node_name, 'node')
-
- node = findByName(lustre, node_name, "node")
- node_add_profile(gen, node, "mds", mds_uuid)
- net_uuid = get_net_uuid(lustre, node_name)
- if not net_uuid:
- error("NODE: ", node_name, "not found")
-
- mds = gen.mds(mds_name, mds_uuid, fstype, devname, get_format_flag(options),
- net_uuid, node_uuid, dev_size=size)
- lustre.appendChild(mds)
-
-
-def add_ost(gen, lustre, options, args):
- lovname = ''
- obdtype = 'obdfilter'
- devname = ''
- size = 0
- fstype = 'extN'
-
- if options.has_key('node'):
- node_name = options['node']
- else:
- error("--ost requires a --node argument")
-
- if options.has_key('lov'):
- lovname = options['lov']
-
- if options.has_key('obdtype'):
- obdtype = options['obdtype']
- if options.has_key('fstype'):
- fstype = options['fstype']
- if obdtype == 'obdecho':
- fstype = ''
- else:
- if len(args) < 1:
- usage()
- devname = args[0]
- if len(args) > 1:
- size = args[1]
-
- obdname = new_name('OBD_'+ node_name)
- oscname = new_name('OSC_'+ node_name)
- ostname = new_name('OST_'+ node_name)
- if options.has_key('obduuid'):
- obd_uuid = options['obduuid']
- obd = lookup(lustre, obd_uuid)
- if obd:
- error("Duplicate OBD UUID:", obd_uuid)
- else:
- obd_uuid = new_uuid(obdname)
- ost_uuid = new_uuid(ostname)
- osc_uuid = new_uuid(oscname)
-
- net_uuid = get_net_uuid(lustre, node_name)
- if not net_uuid:
- error("NODE: ", node_name, "not found")
-
- obd = gen.obd(obdname, obd_uuid, fstype, obdtype, devname, get_format_flag(options), size)
- ost = gen.ost(ostname, ost_uuid, obd_uuid, net_uuid)
- osc = gen.osc(oscname, osc_uuid, obd_uuid, ost_uuid)
-
- if lovname:
- lov = findByName(lustre, lovname, "lov")
- if not lov:
- error('add_ost:', '"'+lovname+'"', "lov element not found.")
- lov_add_osc(gen, lov, osc_uuid)
-
- node = findByName(lustre, node_name, "node")
- node_add_profile(gen, node, 'obd', obd_uuid)
- node_add_profile(gen, node, 'ost', ost_uuid)
-
- lustre.appendChild(obd)
- lustre.appendChild(osc)
- lustre.appendChild(ost)
-
-
-# this is generally only used by llecho.sh
-def add_osc(gen, lustre, options, args):
- """ add the osc to the profile for this node. """
- if len(args) < 1:
- usage()
- osc_name = args[0]
- if options.has_key('node'):
- node_name = options['node']
- else:
- error("--osc requires a --node argument")
- osc_uuid = name2uuid(lustre, osc_name) # either 'osc' or 'lov'
- node = findByName(lustre, node_name, "node")
- node_add_profile(gen, node, 'osc', osc_uuid)
-
-
-#ditto
-def add_echo_client(gen, lustre, options, args):
- """ add an echo client to the profile for this node. """
- if len(args) < 1:
- usage()
- lov_name = args[0]
- if options.has_key('node'):
- node_name = options['node']
- else:
- error("--echo_client requires a --node argument")
- node = findByName(lustre, node_name, "node")
-
- echoname = new_name('ECHO_'+ node_name)
- echo_uuid = new_uuid(echoname)
- node_add_profile(gen, node, 'echo_client', echo_uuid)
-
- lov_uuid = name2uuid(lustre, lov_name, tag='lov', fatal=0)
- if not lov_uuid:
- lov_uuid = name2uuid(lustre, lov_name, tag='osc', fatal=1)
-
- echo = gen.echo_client(echoname, echo_uuid, lov_uuid)
- lustre.appendChild(echo)
-
-
-def add_lov(gen, lustre, options, args):
- """ create a lov """
- if len(args) < 4:
- usage()
-
- name = new_name(options['lov'])
- if name != options['lov']:
- warning("name:", options['lov'], "already used. using:", name)
-
- mds_name = args[0]
- stripe_sz = args[1]
- stripe_count = args[2]
- pattern = args[3]
- uuid = new_uuid(name)
-
- ret = findByName(lustre, name, "lov")
- if ret:
- error("LOV: ", name, " already exists.")
-
- mds_uuid = name2uuid(lustre, mds_name, 'mds')
- lov = gen.lov(name, uuid, mds_uuid, stripe_sz, stripe_count, pattern)
- lustre.appendChild(lov)
-
- # add an lovconfig entry to the mds profile
- lovconfig_name = new_name('LVCFG_' + name)
- lovconfig_uuid = new_uuid(lovconfig_name)
- node = mds2node(lustre, mds_name)
- node_add_profile(gen, node, "lovconfig", lovconfig_uuid)
- lovconfig = gen.lovconfig(lovconfig_name, lovconfig_uuid, uuid)
- lustre.appendChild(lovconfig)
-
-
-
-def add_mtpt(gen, lustre, options, args):
- """ create mtpt on a node """
- if len(args) < 3:
- usage()
-
- if options.has_key('node'):
- node_name = options['node']
- else:
- error("--mtpt requires a --node argument")
-
- path = args[0]
- mds_name = args[1]
- lov_name = args[2]
-
- name = new_name('MNT_'+ node_name)
-
- ret = findByName(lustre, name, "mountpoint")
- if ret:
- error("MOUNTPOINT: ", name, " already exists.")
-
- mds_uuid = name2uuid(lustre, mds_name, tag='mds')
- lov_uuid = name2uuid(lustre, lov_name, tag='lov', fatal=0)
- if not lov_uuid:
- lov_uuid = name2uuid(lustre, lov_name, tag='osc', fatal=1)
-
- uuid = new_uuid(name)
- mtpt = gen.mountpoint(name, uuid, mds_uuid, lov_uuid, path)
- node = findByName(lustre, node_name, "node")
- if not node:
- error('node:', node_name, "not found.")
- node_add_profile(gen, node, "mountpoint", uuid)
- lustre.appendChild(mtpt)
-
-
-############################################################
-# Command line processing
-#
-def parse_cmdline(argv):
- short_opts = "ho:i:m:"
- long_opts = ["ost", "osc", "mtpt", "lov=", "node=", "mds=", "net",
- "echo_client", "tcpbuf=",
- "route", "router", "merge=", "format", "reformat", "output=",
- "obdtype=", "fstype=", "obduuid=", "in=", "help", "batch="]
- opts = []
- args = []
- options = {}
- try:
- opts, args = getopt.getopt(argv, short_opts, long_opts)
- except getopt.error:
- print "invalid opt"
- usage()
-
- for o, a in opts:
- # Commands to create new devices
- if o == "--ost":
- options['ost'] = 1
- if o == "--osc":
- options['osc'] = 1
- if o == "--echo_client":
- options['echo_client'] = 1
- if o == "--mds":
- options['mds'] = a
- if o == "--net":
- options['net'] = 1
- if o == "--mtpt":
- options['mtpt'] = 1
- if o == "--node":
- options['node'] = a
- if o == "--route":
- options['route'] = 1
- if o == "--router":
- options['router'] = 1
- if o == "--lov":
- options['lov'] = a
-
- # Options for commands
- if o == "--obdtype":
- options['obdtype'] = a
- if o == "--fstype":
- options['fstype'] = a
- if o == "--obduuid":
- options['obduuid'] = a
- if o == "--tcpbuf":
- options['tcpbuf'] = a
-
- # lmc options
- if o in ("-h", "--help"):
- usage()
- if o in ("-o", "--output"):
- options['output'] = a
- if o in ("-m", "--merge"):
- options['merge'] = a
- if o == "--format":
- options['format'] = 1
- if o == "--reformat":
- options['reformat'] = 1
- if o == "--batch":
- options['batch'] = a
- if o in ("--in" , "-i"):
- options['in'] = a
-
- return options, args
-
-
-# simple class for profiling
-import time
-class chrono:
- def __init__(self):
- self._start = 0
- def start(self):
- self._stop = 0
- self._start = time.time()
- def stop(self, msg=''):
- self._stop = time.time()
- if msg:
- self.display(msg)
- def dur(self):
- return self._stop - self._start
- def display(self, msg):
- d = self.dur()
- str = '%s: %g secs' % (msg, d)
- print str
-
-############################################################
-# Main
-#
-def do_command(gen, lustre, options, args):
- if options.has_key('ost'):
- add_ost(gen, lustre, options, args)
- elif options.has_key('osc'):
- add_osc(gen, lustre, options, args)
- elif options.has_key('echo_client'):
- add_echo_client(gen, lustre, options, args)
- elif options.has_key('mtpt'):
- add_mtpt(gen, lustre, options, args)
- elif options.has_key('mds'):
- add_mds(gen, lustre, options, args)
- elif options.has_key('net'):
- add_net(gen, lustre, options, args)
- elif options.has_key('lov'):
- add_lov(gen, lustre, options, args)
- elif options.has_key('route'):
- add_route(gen, lustre, options, args)
- elif options.has_key('node'):
- add_node(gen, lustre, options, args)
- else:
- print "Missing command"
- usage()
-
-def main():
- options, args = parse_cmdline(sys.argv[1:])
- outFile = '-'
-
- if options.has_key('merge'):
- outFile = options['merge']
- if os.access(outFile, os.R_OK):
- doc = xml.dom.minidom.parse(outFile)
- else:
- doc = new_lustre(xml.dom.minidom)
- elif options.has_key('in'):
- doc = xml.dom.minidom.parse(options['in'])
- else:
- doc = new_lustre(xml.dom.minidom)
-
- if options.has_key('output'):
- outFile = options['output']
-
- lustre = doc.documentElement
- init_names(lustre)
- if lustre.tagName != "lustre":
- print "Existing config not valid."
- sys.exit(1)
-
- gen = GenConfig(doc)
-
- if options.has_key('batch'):
- fp = open(options['batch'])
- batchCommands = fp.readlines()
- fp.close()
- for cmd in batchCommands:
- options, args = parse_cmdline(string.split(cmd))
- do_command(gen, lustre, options, args)
- else:
- do_command(gen, lustre, options, args)
-
- if outFile == '-':
- PrettyPrint(doc)
- else:
- PrettyPrint(doc, open(outFile,"w"))
-
-if __name__ == "__main__":
- main()
-
-
+++ /dev/null
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-
-/****************** Custom includes ********************/
-#include <linux/lustre_lite.h>
-#include <linux/lustre_idl.h>
-
-
-/****************** Functions ******************/
-
-void usage(char *pgm)
-{
- fprintf(stderr, "\nIncorrect parameters! Correct usage:\n\n" );
- fprintf(stderr, "%s <output filename> <stripe size> <OST #> <stripe #>\n", pgm);
-
- fprintf(stderr, "\n\nArgument explanations:\n---------------------\n\n");
- fprintf(stderr, "<output filename> = the full name and path of the output file to create\n");
- fprintf(stderr, "<stripe size> = the number of bytes to have in each stripe.\n");
- fprintf(stderr, "<OST #> = the OST number to start the striping on.\n");
- fprintf(stderr, "<stripe #> = the number of stripes to use.\n");
-
- fprintf(stderr, "\n\nExamples:\n---------\n\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost1 131072 0 1\n", pgm);
- fprintf(stderr, "\t\tcreates a file only on ost1.\n\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost2 131072 1 1\n", pgm);
- fprintf(stderr, "\t\tcreates a file only on ost2.\n\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost1and2 131072 0 2\n", pgm);
- fprintf(stderr, "\t\tcreates a 128k file with 2 stripes, on ost1 and ost2.\n");
-
- fprintf(stderr, "%s /mnt/lustre/ost1and2 131072 1 2\n", pgm);
- fprintf(stderr, "\t\tcreates a 128k file with 2 stripes, on ost2 and ost1.\n");
-}
-
-int create_file(char *name, long stripe_size, int stripe_offset,
- int stripe_count)
-{
- struct lov_mds_md a_striping;
- int fd, result = 0;
-
- /* Initialize IOCTL striping pattern structure */
- a_striping.lmm_magic = LOV_MAGIC;
- a_striping.lmm_stripe_pattern = 0;
- a_striping.lmm_stripe_size = stripe_size;
- a_striping.lmm_stripe_offset = stripe_offset;
- a_striping.lmm_stripe_count = stripe_count;
-
- fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644);
- if (fd < 0) {
- fprintf(stderr, "\nUnable to open '%s': %s\n",
- name, strerror(errno));
- result = -errno;
- } else if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &a_striping)) {
- fprintf(stderr, "\nError on ioctl for '%s' (%d): %s\n",
- name, fd, strerror(errno));
- result = -errno;
- } else if (close(fd) < 0) {
- fprintf(stderr, "\nError on close for '%s' (%d): %s\n",
- name, fd, strerror(errno));
- result = -errno;
- }
-
- return result;
-}
-
-int main(int argc, char *argv[])
-{
- int result;
- long st_size;
- int st_offset,
- st_count;
-
- /* Check to make sure we have enough parameters */
- if (argc != 5) {
- usage(argv[0]);
- return(-1);
- }
-
- /* Get the stripe size */
- st_size = atol(argv[2]);
-
- /* Get the stripe offset*/
- st_offset = atoi(argv[3]);
-
- /* Get the stripe count */
- st_count = atoi(argv[4]);
-
- /* Create the file, as specified. Return and display any errors. */
- result = create_file(argv[1], st_size, st_offset, st_count);
-
- return result;
-}
+++ /dev/null
-<!-- Lustre Management DTD -->\r
-\r
-<!-- basic entities -->\r
-<!ENTITY % tag.content "(#PCDATA)">\r
-<!ENTITY % tag.ref "\r
- num CDATA #IMPLIED\r
- name CDATA #IMPLIED\r
- uuidref CDATA #REQUIRED">\r
-<!ENTITY % tag.attr "\r
- name CDATA #REQUIRED\r
- uuid CDATA #REQUIRED">\r
-\r
-<!-- main elements -->\r
-<!ELEMENT lustre (node | mountpoint | ldlm | echo_client |\r
- mds | mdc | obd | ost | osc | lov | lovconfig)*>\r
-\r
-<!ELEMENT node (network | profile)*>\r
-<!ATTLIST node router CDATA #IMPLIED\r
- %tag.attr;>\r
-<!ELEMENT network (server | port | route_tbl | send_mem | recv_mem)*>\r
-<!ATTLIST network type (tcp | elan | gm) 'tcp'\r
- %tag.attr;>\r
-\r
-<!ELEMENT route_tbl (route)*>\r
-<!ELEMENT route %tag.content;>\r
-<!ATTLIST route type (elan | tcp | gm) #REQUIRED\r
- gw CDATA #REQUIRED\r
- lo CDATA #REQUIRED\r
- hi CDATA #IMPLIED >\r
-\r
-<!ELEMENT profile (ldlm_ref | network_ref | obd_ref | ost_ref | osc_ref |\r
- echo_client_ref | mds_ref | mdc_ref | lov_ref |\r
- lovconfig_ref| mountpoint_ref)*>\r
-<!ATTLIST profile >\r
-\r
-<!ELEMENT mountpoint (path | fileset | mds_ref | osc_ref)*>\r
-<!ATTLIST mountpoint %tag.attr;>\r
-<!ELEMENT echo_client (osc_ref)*>\r
-<!ATTLIST echo_client %tag.attr;>\r
-<!ELEMENT ldlm EMPTY>\r
-<!ATTLIST ldlm %tag.attr;>\r
-\r
-<!ELEMENT obd (fstype | device | autoformat)*>\r
-<!ATTLIST obd %tag.attr; type (obdfilter | obdecho) 'obdfilter'>\r
-<!ELEMENT ost (network_ref | obd_ref | failover_ref)*>\r
-<!ATTLIST ost %tag.attr;>\r
-<!ELEMENT mds (network_ref | fstype | device | autoformat | \r
- server_ref | failover_ref | node_ref )*>\r
-<!ATTLIST mds %tag.attr;>\r
-\r
-<!ELEMENT osc (ost_ref | obd_ref)*>\r
-<!ATTLIST osc %tag.attr;>\r
-<!ELEMENT mdc (network_ref | mds_ref)*>\r
-<!ATTLIST mdc %tag.attr;>\r
-<!ELEMENT lov (devices | mds_ref)*>\r
-<!ATTLIST lov %tag.attr;>\r
-<!ELEMENT lovconfig (lov_ref)>\r
-<!ATTLIST lovconfig %tag.attr;>\r
-<!ELEMENT devices (osc_ref)+>\r
-<!ATTLIST devices stripesize CDATA #REQUIRED\r
- stripecount CDATA #REQUIRED\r
- stripeoffset CDATA #IMPLIED\r
- pattern CDATA #REQUIRED>\r
-\r
-<!-- basic elements -->\r
-\r
-<!ELEMENT fstype %tag.content;>\r
-<!ELEMENT device %tag.content;>\r
-<!ATTLIST device size CDATA #IMPLIED>\r
-<!ELEMENT server %tag.content;>\r
-<!ELEMENT port %tag.content;>\r
-<!ELEMENT send_mem %tag.content;>\r
-<!ELEMENT recv_mem %tag.content;>\r
-<!ELEMENT autoformat %tag.content;>\r
-<!ELEMENT path %tag.content;>\r
-<!ELEMENT fileset %tag.content;>\r
-\r
-<!-- id tag elements -->\r
-<!ELEMENT network_ref %tag.content;>\r
-<!ATTLIST network_ref %tag.ref;>\r
-<!ELEMENT node_ref %tag.content;>\r
-<!ATTLIST node_ref %tag.ref;>\r
-<!ELEMENT profile_ref %tag.content;>\r
-<!ATTLIST profile_ref %tag.ref;>\r
-<!ELEMENT obd_ref %tag.content;>\r
-<!ATTLIST obd_ref %tag.ref;>\r
-<!ELEMENT mds_ref %tag.content;>\r
-<!ATTLIST mds_ref %tag.ref;>\r
-<!ELEMENT osc_ref %tag.content;>\r
-<!ATTLIST osc_ref %tag.ref;>\r
-<!ELEMENT ost_ref %tag.content;>\r
-<!ATTLIST ost_ref %tag.ref;>\r
-<!ELEMENT lov_ref %tag.content;>\r
-<!ATTLIST lov_ref %tag.ref;>\r
-<!ELEMENT lovconfig_ref %tag.content;>\r
-<!ATTLIST lovconfig_ref %tag.ref;>\r
-<!ELEMENT mdc_ref %tag.content;>\r
-<!ATTLIST mdc_ref %tag.ref;>\r
-<!ELEMENT mountpoint_ref %tag.content;>\r
-<!ATTLIST mountpoint_ref %tag.ref;>\r
-<!ELEMENT echo_client_ref %tag.content;>\r
-<!ATTLIST echo_client_ref %tag.ref;>\r
-<!ELEMENT server_ref %tag.content;>\r
-<!ATTLIST server_ref %tag.ref;>\r
-<!ELEMENT failover_ref %tag.content;>\r
-<!ATTLIST failover_ref %tag.ref;>\r
-<!ELEMENT ldlm_ref %tag.content;>\r
-<!ATTLIST ldlm_ref %tag.ref;>\r
-\r
-\r
+++ /dev/null
-#!/bin/sh
-
-MDS=NET_mds_tcp_UUID
-MDSHOST=mds
-
-/r/src/lustre/utils/lctl <<EOF
-network tcp
-close_uuid $MDS
-del_uuid $MDS
-connect $MDSHOST 988
-add_uuid $MDS $MDSHOST
-quit
-EOF
-
-/r/src/lustre/utils/lctl <<EOF
-device \$RPCDEV
-probe
-newconn $MDS
-quit
-EOF
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * Author: Peter J. Braam <braam@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- * Author: Andreas Dilger <adilger@clusterfs.com>
- * Author: Robert Read <rread@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <signal.h>
-#define printk printf
-
-#include <linux/lustre_lib.h>
-#include <linux/lustre_idl.h>
-#include <linux/lustre_dlm.h>
-#include <linux/obd_lov.h> /* for IOC_LOV_SET_OSC_ACTIVE */
-#include <linux/obd.h> /* for struct lov_stripe_md */
-#include <linux/lustre_build_version.h>
-
-#include <unistd.h>
-#include <sys/un.h>
-#include <time.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <errno.h>
-#include <string.h>
-
-#include <asm/page.h> /* needed for PAGE_SIZE - rread */
-
-#define __KERNEL__
-#include <linux/list.h>
-#undef __KERNEL__
-
-#include "obdctl.h"
-#include "parser.h"
-#include <stdio.h>
-
-#define SHMEM_STATS 1
-#if SHMEM_STATS
-# include <sys/ipc.h>
-# include <sys/shm.h>
-
-# define MAX_SHMEM_COUNT 1024
-static long long *shared_counters;
-static long long counter_snapshot[2][MAX_SHMEM_COUNT];
-struct timeval prev_time;
-#endif
-
-int fd = -1;
-uint64_t conn_addr = -1;
-uint64_t conn_cookie;
-char rawbuf[8192];
-char *buf = rawbuf;
-int max = sizeof(rawbuf);
-
-static int thread;
-static struct lov_stripe_md saved_lsm;
-static char lsm_valid = 0;
-
-static int getfd(char *func);
-static char *cmdname(char *func);
-
-#define IOCINIT(data) \
-do { \
- memset(&data, 0, sizeof(data)); \
- data.ioc_version = OBD_IOCTL_VERSION; \
- data.ioc_addr = conn_addr; \
- data.ioc_cookie = conn_cookie; \
- data.ioc_len = sizeof(data); \
- if (fd < 0) { \
- fprintf(stderr, "No device open, use device\n"); \
- return 1; \
- } \
-} while (0)
-
-#define IOC_PACK(func, data) \
-do { \
- if (obd_ioctl_pack(&data, &buf, max)) { \
- fprintf(stderr, "error: %s: invalid ioctl\n", \
- cmdname(func)); \
- return -2; \
- } \
-} while (0)
-
-#define IOC_UNPACK(func, data) \
-do { \
- if (obd_ioctl_unpack(&data, buf, max)) { \
- fprintf(stderr, "error: %s: invalid reply\n", \
- cmdname(func)); \
- return -2; \
- } \
-} while (0)
-
-char *obdo_print(struct obdo *obd)
-{
- char buf[1024];
-
- sprintf(buf, "id: "LPX64"\ngrp: "LPX64"\natime: "LPU64"\nmtime: "LPU64
- "\nctime: "LPU64"\nsize: "LPU64"\nblocks: "LPU64
- "\nblksize: %u\nmode: %o\nuid: %d\ngid: %d\nflags: %x\n"
- "obdflags: %x\nnlink: %d,\nvalid %x\n",
- obd->o_id, obd->o_gr, obd->o_atime, obd->o_mtime, obd->o_ctime,
- obd->o_size, obd->o_blocks, obd->o_blksize, obd->o_mode,
- obd->o_uid, obd->o_gid, obd->o_flags, obd->o_obdflags,
- obd->o_nlink, obd->o_valid);
- return strdup(buf);
-}
-
-
-#define BAD_VERBOSE (-999999999)
-
-#define N2D_OFF 0x100 /* So we can tell between error codes and devices */
-
-static int do_name2dev(char *func, char *name)
-{
- struct obd_ioctl_data data;
- int rc;
-
- if (getfd(func))
- return -1;
-
- IOCINIT(data);
-
- data.ioc_inllen1 = strlen(name) + 1;
- data.ioc_inlbuf1 = name;
-
- IOC_PACK(func, data);
- rc = ioctl(fd, OBD_IOC_NAME2DEV, buf);
- if (rc < 0) {
- fprintf(stderr, "error: %s: %s - %s\n", cmdname(func),
- name, strerror(rc = errno));
- return rc;
- }
- IOC_UNPACK(func, data);
-
- return data.ioc_dev + N2D_OFF;
-}
-
-/*
- * resolve a device name to a device number.
- * supports a number or name.
- * FIXME: support UUID
- */
-static int parse_devname(char *func, char *name)
-{
- int rc;
- int ret = -1;
-
- if (!name)
- return ret;
- if (name[0] == '$') {
- rc = do_name2dev(func, name + 1);
- if (rc >= N2D_OFF) {
- ret = rc - N2D_OFF;
- printf("%s is device %d\n", name, ret);
- } else {
- fprintf(stderr, "error: %s: %s: %s\n", cmdname(func),
- name, "device not found");
- }
- } else
- ret = strtoul(name, NULL, 0);
-
- return ret;
-}
-
-static char *cmdname(char *func)
-{
- static char buf[512];
-
- if (thread) {
- sprintf(buf, "%s-%d", func, thread);
- return buf;
- }
-
- return func;
-}
-
-static int getfd(char *func)
-{
- if (fd == -1)
- fd = open("/dev/obd", O_RDWR);
- if (fd == -1) {
- fprintf(stderr, "error: %s: opening /dev/obd: %s\n"
- "hint: lustre kernel modules may not be loaded.\n",
- cmdname(func), strerror(errno));
- return -1;
- }
- return 0;
-}
-
-#define difftime(a, b) \
- ((double)(a)->tv_sec - (b)->tv_sec + \
- ((double)((a)->tv_usec - (b)->tv_usec) / 1000000))
-
-static int be_verbose(int verbose, struct timeval *next_time,
- __u64 num, __u64 *next_num, int num_total)
-{
- struct timeval now;
-
- if (!verbose)
- return 0;
-
- if (next_time != NULL)
- gettimeofday(&now, NULL);
-
- /* A positive verbosity means to print every X iterations */
- if (verbose > 0 &&
- (next_num == NULL || num >= *next_num || num >= num_total)) {
- *next_num += verbose;
- if (next_time) {
- next_time->tv_sec = now.tv_sec - verbose;
- next_time->tv_usec = now.tv_usec;
- }
- return 1;
- }
-
- /* A negative verbosity means to print at most each X seconds */
- if (verbose < 0 && next_time != NULL && difftime(&now, next_time) >= 0){
- next_time->tv_sec = now.tv_sec - verbose;
- next_time->tv_usec = now.tv_usec;
- if (next_num)
- *next_num = num;
- return 1;
- }
-
- return 0;
-}
-
-static int get_verbose(char *func, const char *arg)
-{
- int verbose;
- char *end;
-
- if (!arg || arg[0] == 'v')
- verbose = 1;
- else if (arg[0] == 's' || arg[0] == 'q')
- verbose = 0;
- else {
- verbose = (int)strtoul(arg, &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: bad verbose option '%s'\n",
- cmdname(func), arg);
- return BAD_VERBOSE;
- }
- }
-
- if (verbose < 0)
- printf("Print status every %d seconds\n", -verbose);
- else if (verbose == 1)
- printf("Print status every operation\n");
- else if (verbose > 1)
- printf("Print status every %d operations\n", verbose);
-
- return verbose;
-}
-
-int do_disconnect(char *func, int verbose)
-{
- int rc;
- struct obd_ioctl_data data;
-
- if (conn_addr == -1)
- return 0;
-
- IOCINIT(data);
-
- rc = ioctl(fd, OBD_IOC_DISCONNECT, &data);
- if (rc < 0) {
- fprintf(stderr, "error: %s: OPD_IOC_DISCONNECT %s\n",
- cmdname(func),strerror(errno));
- } else {
- if (verbose)
- printf("%s: disconnected conn "LPX64"\n", cmdname(func),
- conn_addr);
- conn_addr = -1;
- }
-
- return rc;
-}
-
-#if SHMEM_STATS
-static void shmem_setup(void)
-{
- /* Create new segment */
- int shmid = shmget(IPC_PRIVATE, sizeof(counter_snapshot[0]), 0600);
-
- if (shmid == -1) {
- fprintf(stderr, "Can't create shared memory counters: %s\n",
- strerror(errno));
- return;
- }
-
- /* Attatch to new segment */
- shared_counters = (long long *)shmat(shmid, NULL, 0);
-
- if (shared_counters == (long long *)(-1)) {
- fprintf(stderr, "Can't attach shared memory counters: %s\n",
- strerror(errno));
- shared_counters = NULL;
- return;
- }
-
- /* Mark segment as destroyed, so it will disappear when we exit.
- * Forks will inherit attached segments, so we should be OK.
- */
- if (shmctl(shmid, IPC_RMID, NULL) == -1) {
- fprintf(stderr, "Can't destroy shared memory counters: %s\n",
- strerror(errno));
- }
-}
-
-static inline void shmem_reset(void)
-{
- if (shared_counters == NULL)
- return;
-
- memset(shared_counters, 0, sizeof(counter_snapshot[0]));
- memset(counter_snapshot, 0, sizeof(counter_snapshot));
- gettimeofday(&prev_time, NULL);
-}
-
-static inline void shmem_bump(void)
-{
- if (shared_counters == NULL || thread <= 0 || thread > MAX_SHMEM_COUNT)
- return;
-
- shared_counters[thread - 1]++;
-}
-
-static void shmem_snap(int n)
-{
- struct timeval this_time;
- int non_zero = 0;
- long long total = 0;
- double secs;
- int i;
-
- if (shared_counters == NULL || n > MAX_SHMEM_COUNT)
- return;
-
- memcpy(counter_snapshot[1], counter_snapshot[0],
- n * sizeof(counter_snapshot[0][0]));
- memcpy(counter_snapshot[0], shared_counters,
- n * sizeof(counter_snapshot[0][0]));
- gettimeofday(&this_time, NULL);
-
- for (i = 0; i < n; i++) {
- long long this_count =
- counter_snapshot[0][i] - counter_snapshot[1][i];
-
- if (this_count != 0) {
- non_zero++;
- total += this_count;
- }
- }
-
- secs = (this_time.tv_sec + this_time.tv_usec / 1000000.0) -
- (prev_time.tv_sec + prev_time.tv_usec / 1000000.0);
-
- printf("%d/%d Total: %f/second\n", non_zero, n, total / secs);
-
- prev_time = this_time;
-}
-
-#define SHMEM_SETUP() shmem_setup()
-#define SHMEM_RESET() shmem_reset()
-#define SHMEM_BUMP() shmem_bump()
-#define SHMEM_SNAP(n) shmem_snap(n)
-#else
-#define SHMEM_SETUP()
-#define SHMEM_RESET()
-#define SHMEM_BUMP()
-#define SHMEM_SNAP(n)
-#endif
-
-extern command_t cmdlist[];
-
-static int do_device(char *func, int dev)
-{
- struct obd_ioctl_data data;
-
- memset(&data, 0, sizeof(data));
-
- data.ioc_dev = dev;
-
- if (getfd(func))
- return -1;
-
- IOC_PACK(func, data);
- return ioctl(fd, OBD_IOC_DEVICE, buf);
-}
-
-int jt_obd_device(int argc, char **argv)
-{
- int rc, dev;
- do_disconnect(argv[0], 1);
-
- if (argc != 2)
- return CMD_HELP;
-
- dev = parse_devname(argv[0], argv[1]);
- if (dev < 0)
- return -1;
-
- rc = do_device(argv[0], dev);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
-
- return rc;
-}
-
-int jt_obd_connect(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- int rc;
-
- IOCINIT(data);
-
- do_disconnect(argv[0], 1);
-
-#warning TODO: implement timeout per lctl usage for probe
- if (argc != 1)
- return CMD_HELP;
-
- rc = ioctl(fd, OBD_IOC_CONNECT, &data);
- if (rc < 0)
- fprintf(stderr, "error: %s: OBD_IOC_CONNECT %s\n",
- cmdname(argv[0]), strerror(rc = errno));
- else {
- conn_addr = data.ioc_addr;
- conn_cookie = data.ioc_cookie;
- }
- return rc;
-}
-
-int jt_obd_disconnect(int argc, char **argv)
-{
- if (argc != 1)
- return CMD_HELP;
-
- if (conn_addr == -1)
- return 0;
-
- return do_disconnect(argv[0], 0);
-}
-
-int jt_opt_device(int argc, char **argv)
-{
- char *arg2[3];
- int ret;
- int rc;
-
- if (argc < 3)
- return CMD_HELP;
-
- rc = do_device("device", parse_devname(argv[0], argv[1]));
-
- if (!rc) {
- arg2[0] = "connect";
- arg2[1] = NULL;
- rc = jt_obd_connect(1, arg2);
- }
-
- if (!rc)
- rc = Parser_execarg(argc - 2, argv + 2, cmdlist);
-
- ret = do_disconnect(argv[0], 0);
- if (!rc)
- rc = ret;
-
- return rc;
-}
-
-int jt_opt_threads(int argc, char **argv)
-{
- __u64 threads, next_thread;
- int verbose;
- int rc = 0;
- char *end;
- int i;
-
- if (argc < 5)
- return CMD_HELP;
-
- threads = strtoull(argv[1], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: invalid page count '%s'\n",
- cmdname(argv[0]), argv[1]);
- return CMD_HELP;
- }
-
- verbose = get_verbose(argv[0], argv[2]);
- if (verbose == BAD_VERBOSE)
- return CMD_HELP;
-
- if (verbose != 0)
- printf("%s: starting "LPD64" threads on device %s running %s\n",
- argv[0], threads, argv[3], argv[4]);
-
- SHMEM_RESET();
-
- for (i = 1, next_thread = verbose; i <= threads; i++) {
- rc = fork();
- if (rc < 0) {
- fprintf(stderr, "error: %s: #%d - %s\n", argv[0], i,
- strerror(rc = errno));
- break;
- } else if (rc == 0) {
- thread = i;
- argv[2] = "--device";
- return jt_opt_device(argc - 2, argv + 2);
- } else if (be_verbose(verbose, NULL, i, &next_thread, threads))
- printf("%s: thread #%d (PID %d) started\n",
- argv[0], i, rc);
- rc = 0;
- }
-
- if (!thread) { /* parent process */
- int live_threads = threads;
-
- while (live_threads > 0) {
- int status;
- pid_t ret;
-
- ret = waitpid(0, &status, verbose < 0 ? WNOHANG : 0);
- if (ret == 0) {
- if (verbose >= 0)
- abort();
-
- sleep(-verbose);
- SHMEM_SNAP(threads);
- continue;
- }
-
- if (ret < 0) {
- fprintf(stderr, "error: %s: wait - %s\n",
- argv[0], strerror(errno));
- if (!rc)
- rc = errno;
- } else {
- /*
- * This is a hack. We _should_ be able to use
- * WIFEXITED(status) to see if there was an
- * error, but it appears to be broken and it
- * always returns 1 (OK). See wait(2).
- */
- int err = WEXITSTATUS(status);
- if (err || WIFSIGNALED(status))
- fprintf(stderr,
- "%s: PID %d had rc=%d\n",
- argv[0], ret, err);
- if (!rc)
- rc = err;
-
- live_threads--;
- }
- }
- }
-
- return rc;
-}
-
-int jt_obd_detach(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- char force = 'F';
- int rc;
-
- IOCINIT(data);
-
- if (argc != 1 && argc != 2)
- return CMD_HELP;
-
- if (argc == 2) {
- data.ioc_inllen1 = 1;
- data.ioc_inlbuf1 = &force;
- }
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, OBD_IOC_DETACH, buf);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
-
- return rc;
-}
-
-int jt_obd_cleanup(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- int rc;
-
- IOCINIT(data);
-
- if (argc != 1)
- return CMD_HELP;
-
- rc = ioctl(fd, OBD_IOC_CLEANUP, &data);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
-
- return rc;
-}
-
-int jt_obd_newdev(int argc, char **argv)
-{
- int rc;
- struct obd_ioctl_data data;
-
- if (getfd(argv[0]))
- return -1;
-
- IOCINIT(data);
-
- if (argc != 1)
- return CMD_HELP;
-
- rc = ioctl(fd, OBD_IOC_NEWDEV, &data);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
- else {
- printf("Current device set to %d\n", data.ioc_dev);
- }
-
- return rc;
-}
-
-int jt_get_version(int argc, char **argv)
-{
- int rc;
- char buf[8192];
- struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
-
- if (getfd(argv[0]))
- return -1;
-
- memset(buf, 0, sizeof(buf));
- data->ioc_version = OBD_IOCTL_VERSION;
- data->ioc_addr = conn_addr;
- data->ioc_cookie = conn_addr;
- data->ioc_len = sizeof(buf);
- data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
-
- if (argc != 1)
- return CMD_HELP;
-
- rc = ioctl(fd, OBD_GET_VERSION, data);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
- else {
- printf("Lustre version: %s\n", data->ioc_bulk);
- }
-
- printf("lctl version: %s\n",BUILD_VERSION);
- return rc;
-}
-
-int jt_obd_list(int argc, char **argv)
-{
- int rc;
- char buf[8192];
- struct obd_ioctl_data *data = (struct obd_ioctl_data *)buf;
-
- if (getfd(argv[0]))
- return -1;
-
- memset(buf, 0, sizeof(buf));
- data->ioc_version = OBD_IOCTL_VERSION;
- data->ioc_addr = conn_addr;
- data->ioc_cookie = conn_addr;
- data->ioc_len = sizeof(buf);
- data->ioc_inllen1 = sizeof(buf) - size_round(sizeof(*data));
-
- if (argc != 1)
- return CMD_HELP;
-
- rc = ioctl(fd, OBD_IOC_LIST, data);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
- else {
- printf("%s", data->ioc_bulk);
- }
-
- return rc;
-}
-
-int jt_obd_attach(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- int rc;
-
- IOCINIT(data);
-
- if (argc != 2 && argc != 3 && argc != 4)
- return CMD_HELP;
-
- data.ioc_inllen1 = strlen(argv[1]) + 1;
- data.ioc_inlbuf1 = argv[1];
- if (argc >= 3) {
- data.ioc_inllen2 = strlen(argv[2]) + 1;
- data.ioc_inlbuf2 = argv[2];
- }
-
- if (argc == 4) {
- data.ioc_inllen3 = strlen(argv[3]) + 1;
- data.ioc_inlbuf3 = argv[3];
- }
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, OBD_IOC_ATTACH, buf);
- if (rc < 0)
- fprintf(stderr, "error: %s: OBD_IOC_ATTACH %s\n",
- cmdname(argv[0]), strerror(rc = errno));
- else if (argc == 3) {
- char name[1024];
- if (strlen(argv[2]) > 128) {
- printf("Name too long to set environment\n");
- return -EINVAL;
- }
- snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]);
- rc = setenv(name, argv[1], 1);
- if (rc) {
- printf("error setting env variable %s\n", name);
- }
- }
-
- return rc;
-}
-
-int jt_obd_name2dev(int argc, char **argv)
-{
- int rc;
-
- if (argc != 2)
- return CMD_HELP;
-
- rc = do_name2dev(argv[0], argv[1]);
- if (rc >= N2D_OFF) {
- int dev = rc - N2D_OFF;
- rc = do_device(argv[0], dev);
- if (rc == 0)
- printf("%d\n", dev);
- }
- return rc;
-}
-
-int jt_obd_setup(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- int rc;
-
- IOCINIT(data);
-
- if (argc > 3)
- return CMD_HELP;
-
- data.ioc_dev = -1;
- if (argc > 1) {
- data.ioc_dev = parse_devname(argv[0], argv[1]);
- if (data.ioc_dev < 0)
- return -1;
- data.ioc_inllen1 = strlen(argv[1]) + 1;
- data.ioc_inlbuf1 = argv[1];
- }
- if (argc == 3) {
- data.ioc_inllen2 = strlen(argv[2]) + 1;
- data.ioc_inlbuf2 = argv[2];
- }
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, OBD_IOC_SETUP, buf);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
-
- return rc;
-}
-
-/* The ioctl API has been extended to provide the LOV stripe metadata to the
- * caller when applicable. This utility, however, only saves the LSM for the
- * latest CREATE. */
-int jt_obd_create(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- struct timeval next_time;
- __u64 count = 1, next_count;
- int verbose = 1, mode = 0100644, rc = 0, i;
- char *end;
-
- IOCINIT(data);
- if (argc < 2 || argc > 4)
- return CMD_HELP;
-
- count = strtoull(argv[1], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
- cmdname(argv[0]), argv[1]);
- return CMD_HELP;
- }
-
- if (argc > 2) {
- mode = strtoul(argv[2], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: invalid mode '%s'\n",
- cmdname(argv[0]), argv[2]);
- return CMD_HELP;
- }
- if (!(mode & S_IFMT))
- mode |= S_IFREG;
- }
-
- if (argc > 3) {
- verbose = get_verbose(argv[0], argv[3]);
- if (verbose == BAD_VERBOSE)
- return CMD_HELP;
- }
-
- printf("%s: "LPD64" objects\n", cmdname(argv[0]), count);
- gettimeofday(&next_time, NULL);
- next_time.tv_sec -= verbose;
-
- for (i = 1, next_count = verbose; i <= count; i++) {
- data.ioc_obdo1.o_mode = mode;
- data.ioc_obdo1.o_id = i;
- data.ioc_obdo1.o_uid = 0;
- data.ioc_obdo1.o_gid = 0;
- data.ioc_obdo1.o_valid = OBD_MD_FLTYPE | OBD_MD_FLMODE |
- OBD_MD_FLID | OBD_MD_FLUID | OBD_MD_FLGID;;
-
- data.ioc_inllen1 = sizeof(saved_lsm);
- data.ioc_inlbuf1 = (char *)&saved_lsm;
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, OBD_IOC_CREATE, buf);
- IOC_UNPACK(argv[0], data);
- fprintf(stderr, "lsm->lsm_o_id: "LPX64"\n",
- saved_lsm.lsm_object_id);
- SHMEM_BUMP();
- if (rc < 0) {
- fprintf(stderr, "error: %s: #%d - %s\n",
- cmdname(argv[0]), i, strerror(rc = errno));
- break;
- }
- if (!(data.ioc_obdo1.o_valid & OBD_MD_FLID)) {
- fprintf(stderr, "error: %s: objid not valid #%d:%08x\n",
- cmdname(argv[0]), i, data.ioc_obdo1.o_valid);
- rc = EINVAL;
- break;
- }
-
- lsm_valid = 1;
-
- if (be_verbose(verbose, &next_time, i, &next_count, count))
- printf("%s: #%d is object id "LPX64"\n",
- cmdname(argv[0]), i, data.ioc_obdo1.o_id);
- }
- return rc;
-}
-
-int jt_obd_setattr(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- char *end;
- int rc;
-
- IOCINIT(data);
- if (argc != 2)
- return CMD_HELP;
-
- data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: invalid objid '%s'\n",
- cmdname(argv[0]), argv[1]);
- return CMD_HELP;
- }
- data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: invalid mode '%s'\n",
- cmdname(argv[0]), argv[2]);
- return CMD_HELP;
- }
- data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
-
- if (lsm_valid == 1) {
- data.ioc_inllen1 = sizeof(saved_lsm);
- data.ioc_inlbuf1 = (char *)&saved_lsm;
- }
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, OBD_IOC_SETATTR, buf);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
-
- return rc;
-}
-
-int jt_obd_destroy(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- struct timeval next_time;
- __u64 count = 1, next_count;
- int verbose = 1;
- __u64 id;
- char *end;
- int rc = 0, i;
-
- IOCINIT(data);
- if (argc < 2 || argc > 4)
- return CMD_HELP;
-
- id = strtoull(argv[1], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: invalid objid '%s'\n",
- cmdname(argv[0]), argv[1]);
- return CMD_HELP;
- }
- if (argc > 2) {
- count = strtoull(argv[2], &end, 0);
- if (*end) {
- fprintf(stderr,
- "error: %s: invalid iteration count '%s'\n",
- cmdname(argv[0]), argv[2]);
- return CMD_HELP;
- }
- }
-
- if (argc > 3) {
- verbose = get_verbose(argv[0], argv[3]);
- if (verbose == BAD_VERBOSE)
- return CMD_HELP;
- }
-
- printf("%s: "LPD64" objects\n", cmdname(argv[0]), count);
- gettimeofday(&next_time, NULL);
- next_time.tv_sec -= verbose;
-
- for (i = 1, next_count = verbose; i <= count; i++, id++) {
- data.ioc_obdo1.o_id = id;
- data.ioc_obdo1.o_mode = S_IFREG | 0644;
- data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLMODE;
-
- data.ioc_inllen1 = sizeof(saved_lsm);
- data.ioc_inlbuf1 = (char *)&saved_lsm;
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, OBD_IOC_DESTROY, buf);
- IOC_UNPACK(argv[0], data);
- SHMEM_BUMP();
- if (rc < 0) {
- fprintf(stderr, "error: %s: objid "LPX64": %s\n",
- cmdname(argv[0]), id, strerror(rc = errno));
- break;
- }
- lsm_valid = 0;
-
- if (be_verbose(verbose, &next_time, i, &next_count, count))
- printf("%s: #%d is object id "LPX64"\n",
- cmdname(argv[0]), i, id);
- }
-
- return rc;
-}
-
-int jt_obd_getattr(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- char *end;
- int rc;
-
- if (argc != 2)
- return CMD_HELP;
-
- IOCINIT(data);
- data.ioc_obdo1.o_id = strtoull(argv[1], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: invalid objid '%s'\n",
- cmdname(argv[0]), argv[1]);
- return CMD_HELP;
- }
- /* to help obd filter */
- data.ioc_obdo1.o_mode = 0100644;
- data.ioc_obdo1.o_valid = 0xffffffff;
- printf("%s: object id "LPX64"\n", cmdname(argv[0]),data.ioc_obdo1.o_id);
-
- if (lsm_valid == 1) {
- data.ioc_inllen1 = sizeof(saved_lsm);
- data.ioc_inlbuf1 = (char *)&saved_lsm;
- }
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, OBD_IOC_GETATTR, buf);
- IOC_UNPACK(argv[0], data);
- if (rc) {
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
- } else {
- printf("%s: object id "LPX64", mode %o\n", cmdname(argv[0]),
- data.ioc_obdo1.o_id, data.ioc_obdo1.o_mode);
- }
- return rc;
-}
-
-int jt_obd_test_getattr(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- struct timeval start, next_time;
- __u64 i, count, next_count;
- int verbose = 1;
- obd_id objid = 3;
- char *end;
- int rc = 0;
-
- if (argc < 2 && argc > 4)
- return CMD_HELP;
-
- IOCINIT(data);
- count = strtoull(argv[1], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: invalid iteration count '%s'\n",
- cmdname(argv[0]), argv[1]);
- return CMD_HELP;
- }
-
- if (argc >= 3) {
- verbose = get_verbose(argv[0], argv[2]);
- if (verbose == BAD_VERBOSE)
- return CMD_HELP;
- }
-
- if (argc >= 4) {
- if (argv[3][0] == 't') {
- objid = strtoull(argv[3] + 1, &end, 0);
- if (thread)
- objid += thread - 1;
- } else
- objid = strtoull(argv[3], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: invalid objid '%s'\n",
- cmdname(argv[0]), argv[3]);
- return CMD_HELP;
- }
- }
-
- gettimeofday(&start, NULL);
- next_time.tv_sec = start.tv_sec - verbose;
- next_time.tv_usec = start.tv_usec;
- if (verbose != 0)
- printf("%s: getting "LPD64" attrs (objid "LPX64"): %s",
- cmdname(argv[0]), count, objid, ctime(&start.tv_sec));
-
- for (i = 1, next_count = verbose; i <= count; i++) {
- data.ioc_obdo1.o_id = objid;
- data.ioc_obdo1.o_mode = S_IFREG;
- data.ioc_obdo1.o_valid = 0xffffffff;
- rc = ioctl(fd, OBD_IOC_GETATTR, &data);
- SHMEM_BUMP();
- if (rc < 0) {
- fprintf(stderr, "error: %s: #"LPD64" - %d:%s\n",
- cmdname(argv[0]), i, errno, strerror(rc = errno));
- break;
- } else {
- if (be_verbose
- (verbose, &next_time, i, &next_count, count))
- printf("%s: got attr #"LPD64"\n",
- cmdname(argv[0]), i);
- }
- }
-
- if (!rc) {
- struct timeval end;
- double diff;
-
- gettimeofday(&end, NULL);
-
- diff = difftime(&end, &start);
-
- --i;
- if (verbose != 0)
- printf("%s: "LPD64" attrs in %.4gs (%.4g attr/s): %s",
- cmdname(argv[0]), i, diff, (double)i / diff,
- ctime(&end.tv_sec));
- }
- return rc;
-}
-
-int jt_obd_test_brw(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- struct timeval start, next_time;
- int pages = 1;
- __u64 count, next_count;
- __u64 objid = 3;
- int verbose = 1, write = 0, rw;
- char *end;
- int thr_offset = 0;
- int i;
- int len;
- int rc = 0;
-
- if (argc < 2 || argc > 6) {
- fprintf(stderr, "error: %s: bad number of arguments: %d\n",
- cmdname(argv[0]), argc);
- return CMD_HELP;
- }
-
- /* make each thread write to a different offset */
- if (argv[1][0] == 't') {
- count = strtoull(argv[1] + 1, &end, 0);
- if (thread)
- thr_offset = thread - 1;
- } else
- count = strtoull(argv[1], &end, 0);
-
- if (*end) {
- fprintf(stderr, "error: %s: bad iteration count '%s'\n",
- cmdname(argv[0]), argv[1]);
- return CMD_HELP;
- }
-
- if (argc >= 3) {
- if (argv[2][0] == 'w' || argv[2][0] == '1')
- write = 1;
- else if (argv[2][0] == 'r' || argv[2][0] == '0')
- write = 0;
- }
-
- if (argc >= 4) {
- verbose = get_verbose(argv[0], argv[3]);
- if (verbose == BAD_VERBOSE)
- return CMD_HELP;
- }
-
- if (argc >= 5) {
- pages = strtoul(argv[4], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: bad page count '%s'\n",
- cmdname(argv[0]), argv[4]);
- return CMD_HELP;
- }
- }
- if (argc >= 6) {
- if (argv[5][0] == 't') {
- objid = strtoull(argv[5] + 1, &end, 0);
- if (thread)
- objid += thread - 1;
- } else
- objid = strtoull(argv[5], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: bad objid '%s'\n",
- cmdname(argv[0]), argv[5]);
- return CMD_HELP;
- }
- }
-
- len = pages * PAGE_SIZE;
-
- IOCINIT(data);
- data.ioc_obdo1.o_id = objid;
- data.ioc_obdo1.o_mode = S_IFREG;
- data.ioc_obdo1.o_valid = OBD_MD_FLID | OBD_MD_FLTYPE | OBD_MD_FLMODE;
- data.ioc_count = len;
- data.ioc_offset = thr_offset * len * count;
-
- if (lsm_valid == 1) {
- data.ioc_inllen1 = sizeof(saved_lsm);
- data.ioc_inlbuf1 = (char *)&saved_lsm;
- }
-
- gettimeofday(&start, NULL);
- next_time.tv_sec = start.tv_sec - verbose;
- next_time.tv_usec = start.tv_usec;
-
- if (verbose != 0)
- printf("%s: %s "LPU64"x%d pages (obj "LPX64", off "LPU64"): %s",
- cmdname(argv[0]), write ? "writing" : "reading", count,
- pages, objid, data.ioc_offset, ctime(&start.tv_sec));
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, OBD_IOC_OPEN, buf);
- IOC_UNPACK(argv[0], data);
- if (rc) {
- fprintf(stderr, "error: brw_open: %s\n", strerror(rc = errno));
- return rc;
- }
-
- rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
- for (i = 1, next_count = verbose; i <= count; i++) {
- rc = ioctl(fd, rw, buf);
- SHMEM_BUMP();
- if (rc) {
- fprintf(stderr, "error: %s: #%d - %s on %s\n",
- cmdname(argv[0]), i, strerror(rc = errno),
- write ? "write" : "read");
- break;
- } else if (be_verbose(verbose, &next_time,i, &next_count,count))
- printf("%s: %s number %dx%d\n", cmdname(argv[0]),
- write ? "write" : "read", i, pages);
-
- data.ioc_offset += len;
- }
-
- if (!rc) {
- struct timeval end;
- double diff;
-
- gettimeofday(&end, NULL);
-
- diff = difftime(&end, &start);
-
- --i;
- if (verbose != 0)
- printf("%s: %s %dx%d pages in %.4gs (%.4g pg/s): %s",
- cmdname(argv[0]), write ? "wrote" : "read",
- i, pages, diff, (double)i * pages / diff,
- ctime(&end.tv_sec));
- }
- rw = ioctl(fd, OBD_IOC_CLOSE, buf);
- if (rw) {
- fprintf(stderr, "error: brw_close: %s\n", strerror(rw = errno));
- if (!rc)
- rc = rw;
- }
-
- return rc;
-}
-
-int jt_obd_lov_setconfig(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- struct lov_desc desc;
- obd_uuid_t *uuidarray, *ptr;
- int rc, i;
- char *end;
-
- IOCINIT(data);
-
- if (argc <= 6)
- return CMD_HELP;
-
- if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) {
- fprintf(stderr,
- "error: %s: LOV uuid '%s' longer than %zd characters\n",
- cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1);
- return -EINVAL;
- }
-
- memset(&desc, 0, sizeof(desc));
- strncpy(desc.ld_uuid, argv[1], sizeof(desc.ld_uuid) - 1);
- desc.ld_tgt_count = argc - 6;
- desc.ld_default_stripe_count = strtoul(argv[2], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: bad default stripe count '%s'\n",
- cmdname(argv[0]), argv[2]);
- return CMD_HELP;
- }
- if (desc.ld_default_stripe_count > desc.ld_tgt_count) {
- fprintf(stderr,
- "error: %s: default stripe count %u > OST count %u\n",
- cmdname(argv[0]), desc.ld_default_stripe_count,
- desc.ld_tgt_count);
- return -EINVAL;
- }
-
- desc.ld_default_stripe_size = strtoull(argv[3], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: bad default stripe size '%s'\n",
- cmdname(argv[0]), argv[3]);
- return CMD_HELP;
- }
- if (desc.ld_default_stripe_size < 4096) {
- fprintf(stderr,
- "error: %s: default stripe size "LPU64" too small\n",
- cmdname(argv[0]), desc.ld_default_stripe_size);
- return -EINVAL;
- } else if ((long)desc.ld_default_stripe_size <
- desc.ld_default_stripe_size) {
- fprintf(stderr,
- "error: %s: default stripe size "LPU64" too large\n",
- cmdname(argv[0]), desc.ld_default_stripe_size);
- return -EINVAL;
- }
- desc.ld_default_stripe_offset = strtoull(argv[4], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: bad default stripe offset '%s'\n",
- cmdname(argv[0]), argv[4]);
- return CMD_HELP;
- }
- desc.ld_pattern = strtoul(argv[5], &end, 0);
- if (*end) {
- fprintf(stderr, "error: %s: bad stripe pattern '%s'\n",
- cmdname(argv[0]), argv[5]);
- return CMD_HELP;
- }
-
- /* NOTE: it is possible to overwrite the default striping parameters,
- * but EXTREME care must be taken when saving the OST UUID list.
- * It must be EXACTLY the same, or have only additions at the
- * end of the list, or only overwrite individual OST entries
- * that are restored from backups of the previous OST.
- */
- uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
- if (!uuidarray) {
- fprintf(stderr, "error: %s: no memory for %d UUIDs\n",
- cmdname(argv[0]), desc.ld_tgt_count);
- rc = -ENOMEM;
- goto out;
- }
- for (i = 6, ptr = uuidarray; i < argc; i++, ptr++) {
- if (strlen(argv[i]) >= sizeof(*ptr)) {
- fprintf(stderr, "error: %s: arg %d (%s) too long\n",
- cmdname(argv[0]), i, argv[i]);
- rc = -EINVAL;
- goto out;
- }
- strcpy((char *)ptr, argv[i]);
- }
-
- data.ioc_inllen1 = sizeof(desc);
- data.ioc_inlbuf1 = (char *)&desc;
- data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
- data.ioc_inlbuf2 = (char *)uuidarray;
-
- if (obd_ioctl_pack(&data, &buf, max)) {
- fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
- rc = -EINVAL;
- goto out;
- }
- rc = ioctl(fd, OBD_IOC_LOV_SET_CONFIG, buf);
- if (rc)
- fprintf(stderr, "error: %s: ioctl error: %s\n",
- cmdname(argv[0]), strerror(rc = errno));
-out:
- free(uuidarray);
- return rc;
-}
-
-#define DEF_UUID_ARRAY_LEN (8192 / 40)
-
-int jt_obd_lov_getconfig(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- struct lov_desc desc;
- obd_uuid_t *uuidarray;
- int rc;
-
- IOCINIT(data);
-
- if (argc != 2)
- return CMD_HELP;
-
- if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) {
- fprintf(stderr,
- "error: %s: LOV uuid '%s' longer than %zd characters\n",
- cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1);
- return -EINVAL;
- }
-
- memset(&desc, 0, sizeof(desc));
- strncpy(desc.ld_uuid, argv[1], sizeof(desc.ld_uuid) - 1);
- desc.ld_tgt_count = DEF_UUID_ARRAY_LEN;
-repeat:
- uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray));
- if (!uuidarray) {
- fprintf(stderr, "error: %s: no memory for %d uuid's\n",
- cmdname(argv[0]), desc.ld_tgt_count);
- return -ENOMEM;
- }
-
- data.ioc_inllen1 = sizeof(desc);
- data.ioc_inlbuf1 = (char *)&desc;
- data.ioc_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray);
- data.ioc_inlbuf2 = (char *)uuidarray;
-
- if (obd_ioctl_pack(&data, &buf, max)) {
- fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
- rc = -EINVAL;
- goto out;
- }
- rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
- if (rc == -ENOSPC) {
- free(uuidarray);
- goto repeat;
- } else if (rc) {
- fprintf(stderr, "error: %s: ioctl error: %s\n",
- cmdname(argv[0]), strerror(rc = errno));
- } else {
- obd_uuid_t *ptr;
- int i;
-
- if (obd_ioctl_unpack(&data, buf, max)) {
- fprintf(stderr, "error: %s: invalid reply\n",
- cmdname(argv[0]));
- rc = -EINVAL;
- goto out;
- }
- printf("default_stripe_count: %u\n",
- desc.ld_default_stripe_count);
- printf("default_stripe_size: "LPU64"\n",
- desc.ld_default_stripe_size);
- printf("default_stripe_offset: "LPU64"\n",
- desc.ld_default_stripe_offset);
- printf("default_stripe_pattern: %u\n", desc.ld_pattern);
- printf("obd_count: %u\n", desc.ld_tgt_count);
- for (i = 0, ptr = uuidarray; i < desc.ld_tgt_count; i++, ptr++)
- printf("%u: %s\n", i, (char *)ptr);
- }
-out:
- free(uuidarray);
- return rc;
-}
-
-int jt_obd_test_ldlm(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- int rc;
-
- IOCINIT(data);
- if (argc != 1)
- return CMD_HELP;
-
- rc = ioctl(fd, IOC_LDLM_TEST, &data);
- if (rc)
- fprintf(stderr, "error: %s: test failed: %s\n",
- cmdname(argv[0]), strerror(rc = errno));
- return rc;
-}
-
-int jt_obd_dump_ldlm(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- int rc;
-
- IOCINIT(data);
- if (argc != 1)
- return CMD_HELP;
-
- rc = ioctl(fd, IOC_LDLM_DUMP, &data);
- if (rc)
- fprintf(stderr, "error: %s failed: %s\n",
- cmdname(argv[0]), strerror(rc = errno));
- return rc;
-}
-
-int jt_obd_ldlm_regress_start(int argc, char **argv)
-{
- int rc;
- struct obd_ioctl_data data;
- char argstring[200];
- int i, count = sizeof(argstring) - 1;
-
- IOCINIT(data);
- if (argc > 5)
- return CMD_HELP;
-
- argstring[0] = '\0';
- for (i = 1; i < argc; i++) {
- strncat(argstring, " ", count);
- count--;
- strncat(argstring, argv[i], count);
- count -= strlen(argv[i]);
- }
-
- if (strlen(argstring)) {
- data.ioc_inlbuf1 = argstring;
- data.ioc_inllen1 = strlen(argstring) + 1;
- }
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, IOC_LDLM_REGRESS_START, buf);
- if (rc)
- fprintf(stderr, "error: %s: test failed: %s\n",
- cmdname(argv[0]), strerror(rc = errno));
-
- return rc;
-}
-
-int jt_obd_ldlm_regress_stop(int argc, char **argv)
-{
- int rc;
- struct obd_ioctl_data data;
- IOCINIT(data);
-
- if (argc != 1)
- return CMD_HELP;
-
- rc = ioctl(fd, IOC_LDLM_REGRESS_STOP, &data);
-
- if (rc)
- fprintf(stderr, "error: %s: test failed: %s\n",
- cmdname(argv[0]), strerror(rc = errno));
- return rc;
-}
-
-int jt_obd_lov_set_osc_active(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- int rc;
-
- IOCINIT(data);
- if (argc != 3)
- return CMD_HELP;
-
- data.ioc_inlbuf1 = argv[1];
- data.ioc_inllen1 = strlen(argv[1]) + 1;
-
- /* reuse offset for 'active' */
- data.ioc_offset = atoi(argv[2]);
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, IOC_LOV_SET_OSC_ACTIVE, buf);
- if (rc)
- fprintf(stderr, "error: %s: failed: %s\n",
- cmdname(argv[0]), strerror(rc = errno));
-
- return rc;
-}
-
-int jt_obd_newconn(int argc, char **argv)
-{
- int rc;
- struct obd_ioctl_data data;
-
- IOCINIT(data);
- if (argc < 2 || argc > 3)
- return CMD_HELP;
-
- data.ioc_inllen1 = strlen(argv[1]) + 1;
- data.ioc_inlbuf1 = argv[1];
-
- if (argc == 3) {
- data.ioc_inllen2 = strlen(argv[2]) + 1;
- data.ioc_inlbuf2 = argv[2];
- }
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, OBD_IOC_RECOVD_NEWCONN, buf);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
-
- return rc;
-}
-
-int jt_obd_failconn(int argc, char **argv)
-{
- int rc;
- struct obd_ioctl_data data;
-
- IOCINIT(data);
- if (argc < 2)
- return CMD_HELP;
-
- data.ioc_inllen1 = strlen(argv[1]) + 1;
- data.ioc_inlbuf1 = argv[1];
-
- IOC_PACK(argv[0], data);
- rc = ioctl(fd, OBD_IOC_RECOVD_FAILCONN, buf);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
-
- return rc;
-}
-
-static void signal_server(int sig)
-{
- if (sig == SIGINT) {
- do_disconnect("sigint", 1);
- exit(1);
- } else
- fprintf(stderr, "%s: got signal %d\n", cmdname("sigint"), sig);
-}
-
-int obd_initialize(int argc, char **argv)
-{
- SHMEM_SETUP();
- return 0;
-}
-
-
-void obd_cleanup(int argc, char **argv)
-{
- struct sigaction sigact;
-
- sigact.sa_handler = signal_server;
- sigfillset(&sigact.sa_mask);
- sigact.sa_flags = SA_RESTART;
- sigaction(SIGINT, &sigact, NULL);
-
- do_disconnect(argv[0], 1);
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- * Author: Peter J. Braam <braam@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "obdctl.h"
-#include "parser.h"
-
-/* the functions that were in here are now in obd.c */
-
-static int jt_quit(int argc, char **argv)
-{
- int rc = 0;
- Parser_quit(argc, argv);
-
- return rc;
-}
-
-command_t cmdlist[] = {
- /* Metacommands */
- {"--device", jt_opt_device, 0, "--device <devno> <command [args ...]>"},
- {"--threads", jt_opt_threads, 0,
- "--threads <threads> <devno> <command [args ...]>"},
-
- /* Device configuration commands */
- {"lov_setconfig", jt_obd_lov_setconfig, 0, "configure lov data on MDS "
- "[usage: lovconfig lov-uuid stripecount, stripesize, pattern, UUID1, [UUID2, ...]"},
- {"list", jt_obd_list, 0, "list the devices (no args)"},
- {"newdev", jt_obd_newdev, 0, "set device to a new unused obd (no args)"},
- {"device", jt_obd_device, 0, "set current device (args device_no name)"},
- {"name2dev", jt_obd_name2dev, 0,
- "set device by name [usage: name2dev devname]"},
- {"attach", jt_obd_attach, 0, "name the type of device (args: type data"},
- {"setup", jt_obd_setup, 0, "setup device (args: <blkdev> [data]"},
- {"detach", jt_obd_detach, 0, "detach the current device (arg: )"},
- {"cleanup", jt_obd_cleanup, 0, "cleanup the current device (arg: )"},
-
- /* Session commands */
- {"connect", jt_obd_connect, 0, "connect - get a connection to device"},
- {"disconnect", jt_obd_disconnect, 0,
- "disconnect - break connection to device"},
-
- /* Session operations */
- {"create", jt_obd_create, 0, "create <count> [mode [verbose]]"},
- {"destroy", jt_obd_destroy, 0, "destroy <id> [count [verbose]]"},
- {"getattr", jt_obd_getattr, 0, "getattr <id>"},
- {"setattr", jt_obd_setattr, 0, "setattr <id> <mode>"},
- {"newconn", jt_obd_newconn, 0, "newconn <olduuid> [newuuid]"},
- {"test_getattr", jt_obd_test_getattr, 0, "test_getattr <count> [verbose [[t]objid]]"},
- {"test_brw", jt_obd_test_brw, 0, "test_brw [t]<count> [write [verbose [pages [[t]objid]]]]"},
- {"test_ldlm", jt_obd_test_ldlm, 0, "test lock manager (no args)"},
- {"dump_ldlm", jt_obd_dump_ldlm, 0, "dump all lock manager state (no args)"},
-
- /* User interface commands */
- {"help", Parser_help, 0, "help"},
- {"exit", jt_quit, 0, "quit"},
- {"quit", jt_quit, 0, "quit"},
- {0, 0, 0, NULL}
-};
-
-
-int main(int argc, char **argv)
-{
- int rc;
-
- setlinebuf(stdout);
-
- if (obd_initialize(argc, argv) < 0)
- exit(1);
-
- if (argc > 1) {
- rc = Parser_execarg(argc - 1, argv + 1, cmdlist);
- } else {
- Parser_init("obdctl > ", cmdlist);
- rc = Parser_commands();
- }
-
- obd_cleanup(argc, argv);
- return rc;
-}
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2002 Cluster File Systems, Inc.
- *
- * Author: Peter J. Braam <braam@clusterfs.com>
- * Author: Phil Schwan <phil@clusterfs.com>
- * Author: Robert Read <rread@clusterfs.com>
- *
- * This file is part of Lustre, http://www.lustre.org.
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#ifndef _OBDCTL_H_
-#define _OBDCTL_H_
-
-int do_disconnect(char *func, int verbose);
-int obd_initialize(int argc, char **argv);
-void obd_cleanup(int argc, char **argv);
-
-int jt_opt_device(int argc, char **argv);
-int jt_opt_threads(int argc, char **argv);
-
-int jt_obd_device(int argc, char **argv);
-int jt_obd_connect(int argc, char **argv);
-int jt_obd_disconnect(int argc, char **argv);
-int jt_obd_detach(int argc, char **argv);
-int jt_obd_cleanup(int argc, char **argv);
-int jt_obd_newdev(int argc, char **argv);
-int jt_obd_list(int argc, char **argv);
-int jt_obd_attach(int argc, char **argv);
-int jt_obd_name2dev(int argc, char **argv);
-int jt_obd_setup(int argc, char **argv);
-int jt_obd_create(int argc, char **argv);
-int jt_obd_setattr(int argc, char **argv);
-int jt_obd_destroy(int argc, char **argv);
-int jt_obd_getattr(int argc, char **argv);
-int jt_obd_test_getattr(int argc, char **argv);
-int jt_obd_test_brw(int argc, char **argv);
-int jt_obd_lov_setconfig(int argc, char **argv);
-int jt_obd_lov_getconfig(int argc, char **argv);
-int jt_obd_test_ldlm(int argc, char **argv);
-int jt_obd_ldlm_regress_start(int argc, char **argv);
-int jt_obd_ldlm_regress_stop(int argc, char **argv);
-int jt_obd_dump_ldlm(int argc, char **argv);
-int jt_obd_lov_set_osc_active(int argc, char **argv);
-int jt_obd_newconn(int argc, char **argv);
-int jt_obd_failconn(int argc, char **argv);
-int jt_get_version(int argc, char **argv);
-
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001 Cluster File Systems, Inc.
- *
- * This file is part of Lustre, http://www.sf.net/projects/lustre/
- *
- * Lustre is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * Lustre 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 Lustre; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <assert.h>
-
-#ifdef HAVE_LIBREADLINE
-#define READLINE_LIBRARY
-#include <readline/readline.h>
-
-//extern char **completion_matches __P((char *, rl_compentry_func_t *));
-extern void using_history(void);
-extern void stifle_history(int);
-extern void add_history(char *);
-#endif
-
-#include "parser.h"
-
-static command_t * top_level; /* Top level of commands, initialized by
- * InitParser */
-static char * parser_prompt = NULL;/* Parser prompt, set by InitParser */
-static int done; /* Set to 1 if user types exit or quit */
-static int ignore_errors; /* Normally, the parser will quit when
- an error occurs in non-interacive
- mode. Setting this to non-zero will
- force it to keep buggering on. */
-
-
-/* static functions */
-static char *skipwhitespace(char *s);
-static char *skiptowhitespace(char *s);
-static command_t *find_cmd(char *name, command_t cmds[], char **next);
-static int process(char *s, char **next, command_t *lookup, command_t **result,
- char **prev);
-static void print_commands(char *str, command_t *table);
-
-static char * skipwhitespace(char * s)
-{
- char * t;
- int len;
-
- len = (int)strlen(s);
- for (t = s; t <= s + len && isspace(*t); t++);
- return(t);
-}
-
-
-static char * skiptowhitespace(char * s)
-{
- char * t;
-
- for (t = s; *t && !isspace(*t); t++);
- return(t);
-}
-
-static int line2args(char *line, char **argv, int maxargs)
-{
- char *arg;
- int i = 0;
-
- arg = strtok(line, " \t");
- if ( arg ) {
- argv[i] = arg;
- i++;
- } else
- return 0;
-
- while( (arg = strtok(NULL, " \t")) && (i <= maxargs)) {
- argv[i] = arg;
- i++;
- }
- return i;
-}
-
-/* find a command -- return it if unique otherwise print alternatives */
-static command_t *Parser_findargcmd(char *name, command_t cmds[])
-{
- command_t *cmd;
-
- for (cmd = cmds; cmd->pc_name; cmd++) {
- if (strcmp(name, cmd->pc_name) == 0)
- return cmd;
- }
- return NULL;
-}
-
-void Parser_ignore_errors(int ignore)
-{
- ignore_errors = ignore;
-}
-
-int Parser_execarg(int argc, char **argv, command_t cmds[])
-{
- command_t *cmd;
-
- cmd = Parser_findargcmd(argv[0], cmds);
- if ( cmd ) {
- return (cmd->pc_func)(argc, argv);
- } else {
- printf("Try interactive use without arguments or use one of:\n");
- for (cmd = cmds; cmd->pc_name; cmd++)
- printf("\"%s\"\n", cmd->pc_name);
- printf("as argument.\n");
- }
- return -1;
-}
-
-/* returns the command_t * (NULL if not found) corresponding to a
- _partial_ match with the first token in name. It sets *next to
- point to the following token. Does not modify *name. */
-static command_t * find_cmd(char * name, command_t cmds[], char ** next)
-{
- int i, len;
-
- if (!cmds || !name )
- return NULL;
-
- /* This sets name to point to the first non-white space character,
- and next to the first whitespace after name, len to the length: do
- this with strtok*/
- name = skipwhitespace(name);
- *next = skiptowhitespace(name);
- len = *next - name;
- if (len == 0)
- return NULL;
-
- for (i = 0; cmds[i].pc_name; i++) {
- if (strncasecmp(name, cmds[i].pc_name, len) == 0) {
- *next = skipwhitespace(*next);
- return(&cmds[i]);
- }
- }
- return NULL;
-}
-
-/* Recursively process a command line string s and find the command
- corresponding to it. This can be ambiguous, full, incomplete,
- non-existent. */
-static int process(char *s, char ** next, command_t *lookup,
- command_t **result, char **prev)
-{
- *result = find_cmd(s, lookup, next);
- *prev = s;
-
- /* non existent */
- if ( ! *result )
- return CMD_NONE;
-
- /* found entry: is it ambigous, i.e. not exact command name and
- more than one command in the list matches. Note that find_cmd
- points to the first ambiguous entry */
- if ( strncasecmp(s, (*result)->pc_name, strlen((*result)->pc_name)) &&
- find_cmd(s, (*result) + 1, next))
- return CMD_AMBIG;
-
- /* found a unique command: component or full? */
- if ( (*result)->pc_func ) {
- return CMD_COMPLETE;
- } else {
- if ( *next == '\0' ) {
- return CMD_INCOMPLETE;
- } else {
- return process(*next, next, (*result)->pc_sub_cmd, result, prev);
- }
- }
-}
-
-#ifdef HAVE_LIBREADLINE
-static command_t * match_tbl; /* Command completion against this table */
-static char * command_generator(const char * text, int state)
-{
- static int index,
- len;
- char *name;
-
- /* Do we have a match table? */
- if (!match_tbl)
- return NULL;
-
- /* If this is the first time called on this word, state is 0 */
- if (!state) {
- index = 0;
- len = (int)strlen(text);
- }
-
- /* Return next name in the command list that paritally matches test */
- while ( (name = (match_tbl + index)->pc_name) ) {
- index++;
-
- if (strncasecmp(name, text, len) == 0) {
- return(strdup(name));
- }
- }
-
- /* No more matches */
- return NULL;
-}
-
-/* probably called by readline */
-static char **command_completion(char * text, int start, int end)
-{
- command_t * table;
- char * pos;
-
- match_tbl = top_level;
- for (table = find_cmd(rl_line_buffer, match_tbl, &pos);
- table;
- table = find_cmd(pos, match_tbl, &pos)) {
-
- if (*(pos - 1) == ' ') match_tbl = table->pc_sub_cmd;
- }
-
- return(completion_matches(text, command_generator));
-}
-#endif
-
-/* take a string and execute the function or print help */
-int execute_line(char * line)
-{
- command_t *cmd, *ambig;
- char *prev;
- char *next, *tmp;
- char *argv[MAXARGS];
- int i;
- int rc = 0;
-
- switch( process(line, &next, top_level, &cmd, &prev) ) {
- case CMD_AMBIG:
- fprintf(stderr, "Ambiguous command \'%s\'\nOptions: ", line);
- while( (ambig = find_cmd(prev, cmd, &tmp)) ) {
- fprintf(stderr, "%s ", ambig->pc_name);
- cmd = ambig + 1;
- }
- fprintf(stderr, "\n");
- break;
- case CMD_NONE:
- fprintf(stderr, "No such command, type help\n");
- break;
- case CMD_INCOMPLETE:
- fprintf(stderr,
- "'%s' incomplete command. Use '%s x' where x is one of:\n",
- line, line);
- fprintf(stderr, "\t");
- for (i = 0; cmd->pc_sub_cmd[i].pc_name; i++) {
- fprintf(stderr, "%s ", cmd->pc_sub_cmd[i].pc_name);
- }
- fprintf(stderr, "\n");
- break;
- case CMD_COMPLETE:
- i = line2args(line, argv, MAXARGS);
- rc = (cmd->pc_func)(i, argv);
-
- if (rc == CMD_HELP)
- fprintf(stderr, "%s\n", cmd->pc_help);
-
- break;
- }
-
- return rc;
-}
-
-int
-noop_fn ()
-{
- return (0);
-}
-
-/* just in case you're ever in an airplane and discover you
- forgot to install readline-dev. :) */
-int init_input()
-{
- int interactive = isatty (fileno (stdin));
-
-#ifdef HAVE_LIBREADLINE
- using_history();
- stifle_history(HISTORY);
-
- if (!interactive)
- {
- rl_prep_term_function = (rl_vintfunc_t *)noop_fn;
- rl_deprep_term_function = (rl_voidfunc_t *)noop_fn;
- }
-
- rl_attempted_completion_function = (CPPFunction *)command_completion;
- rl_completion_entry_function = (void *)command_generator;
-#endif
- return interactive;
-}
-
-#ifndef HAVE_LIBREADLINE
-#define add_history(s)
-char * readline(char * prompt)
-{
- char line[2048];
- int n = 0;
- if (prompt)
- printf ("%s", prompt);
- if (fgets(line, sizeof(line), stdin) == NULL)
- return (NULL);
- n = strlen(line);
- if (n && line[n-1] == '\n')
- line[n-1] = '\0';
- return strdup(line);
-}
-#endif
-
-/* this is the command execution machine */
-int Parser_commands(void)
-{
- char *line, *s;
- int rc = 0, save_error = 0;
- int interactive;
-
- interactive = init_input();
-
- while(!done) {
- line = readline(interactive ? parser_prompt : NULL);
-
- if (!line) break;
-
- s = skipwhitespace(line);
-
- if (*s) {
- add_history(s);
- rc = execute_line(s);
- }
- /* stop on error if not-interactive */
- if (rc != 0 && !interactive) {
- if (save_error == 0)
- save_error = rc;
- if (!ignore_errors)
- done = 1;
- }
-
- free(line);
- }
- if (save_error)
- rc = save_error;
- return rc;
-}
-
-
-/* sets the parser prompt */
-void Parser_init(char * prompt, command_t * cmds)
-{
- done = 0;
- top_level = cmds;
- if (parser_prompt) free(parser_prompt);
- parser_prompt = strdup(prompt);
-}
-
-/* frees the parser prompt */
-void Parser_exit(int argc, char *argv[])
-{
- done = 1;
- free(parser_prompt);
- parser_prompt = NULL;
-}
-
-/* convert a string to an integer */
-int Parser_int(char *s, int *val)
-{
- int ret;
-
- if (*s != '0')
- ret = sscanf(s, "%d", val);
- else if (*(s+1) != 'x')
- ret = sscanf(s, "%o", val);
- else {
- s++;
- ret = sscanf(++s, "%x", val);
- }
-
- return(ret);
-}
-
-
-void Parser_qhelp(int argc, char *argv[]) {
-
- printf("Available commands are:\n");
-
- print_commands(NULL, top_level);
- printf("For more help type: help command-name\n");
-}
-
-int Parser_help(int argc, char **argv)
-{
- char line[1024];
- char *next, *prev, *tmp;
- command_t *result, *ambig;
- int i;
-
- if ( argc == 1 ) {
- Parser_qhelp(argc, argv);
- return 0;
- }
-
- line[0]='\0';
- for ( i = 1 ; i < argc ; i++ ) {
- strcat(line, argv[i]);
- }
-
- switch ( process(line, &next, top_level, &result, &prev) ) {
- case CMD_COMPLETE:
- fprintf(stderr, "%s: %s\n",line, result->pc_help);
- break;
- case CMD_NONE:
- fprintf(stderr, "%s: Unknown command.\n", line);
- break;
- case CMD_INCOMPLETE:
- fprintf(stderr,
- "'%s' incomplete command. Use '%s x' where x is one of:\n",
- line, line);
- fprintf(stderr, "\t");
- for (i = 0; result->pc_sub_cmd[i].pc_name; i++) {
- fprintf(stderr, "%s ", result->pc_sub_cmd[i].pc_name);
- }
- fprintf(stderr, "\n");
- break;
- case CMD_AMBIG:
- fprintf(stderr, "Ambiguous command \'%s\'\nOptions: ", line);
- while( (ambig = find_cmd(prev, result, &tmp)) ) {
- fprintf(stderr, "%s ", ambig->pc_name);
- result = ambig + 1;
- }
- fprintf(stderr, "\n");
- break;
- }
- return 0;
-}
-
-
-void Parser_printhelp(char *cmd)
-{
- char *argv[] = { "help", cmd };
- Parser_help(2, argv);
-}
-
-
-/*************************************************************************
- * COMMANDS *
- *************************************************************************/
-
-
-static void print_commands(char * str, command_t * table) {
- command_t * cmds;
- char buf[80];
-
- for (cmds = table; cmds->pc_name; cmds++) {
- if (cmds->pc_func) {
- if (str) printf("\t%s %s\n", str, cmds->pc_name);
- else printf("\t%s\n", cmds->pc_name);
- }
- if (cmds->pc_sub_cmd) {
- if (str) {
- sprintf(buf, "%s %s", str, cmds->pc_name);
- print_commands(buf, cmds->pc_sub_cmd);
- } else {
- print_commands(cmds->pc_name, cmds->pc_sub_cmd);
- }
- }
- }
-}
-
-char *Parser_getstr(const char *prompt, const char *deft, char *res,
- size_t len)
-{
- char *line = NULL;
- int size = strlen(prompt) + strlen(deft) + 8;
- char *theprompt;
- theprompt = malloc(size);
- assert(theprompt);
-
- sprintf(theprompt, "%s [%s]: ", prompt, deft);
-
- line = readline(theprompt);
- free(theprompt);
-
- if ( line == NULL || *line == '\0' ) {
- strncpy(res, deft, len);
- } else {
- strncpy(res, line, len);
- }
-
- if ( line ) {
- free(line);
- return res;
- } else {
- return NULL;
- }
-}
-
-/* get integer from prompt, loop forever to get it */
-int Parser_getint(const char *prompt, long min, long max, long deft, int base)
-{
- int rc;
- long result;
- char *line;
- int size = strlen(prompt) + 40;
- char *theprompt = malloc(size);
- assert(theprompt);
- sprintf(theprompt,"%s [%ld, (0x%lx)]: ", prompt, deft, deft);
-
- fflush(stdout);
-
- do {
- line = NULL;
- line = readline(theprompt);
- if ( !line ) {
- fprintf(stdout, "Please enter an integer.\n");
- fflush(stdout);
- continue;
- }
- if ( *line == '\0' ) {
- free(line);
- result = deft;
- break;
- }
- rc = Parser_arg2int(line, &result, base);
- free(line);
- if ( rc != 0 ) {
- fprintf(stdout, "Invalid string.\n");
- fflush(stdout);
- } else if ( result > max || result < min ) {
- fprintf(stdout, "Error: response must lie between %ld and %ld.\n",
- min, max);
- fflush(stdout);
- } else {
- break;
- }
- } while ( 1 ) ;
-
- if (theprompt)
- free(theprompt);
- return result;
-
-}
-
-/* get boolean (starting with YyNn; loop forever */
-int Parser_getbool(const char *prompt, int deft)
-{
- int result = 0;
- char *line;
- int size = strlen(prompt) + 8;
- char *theprompt = malloc(size);
- assert(theprompt);
-
- fflush(stdout);
-
- if ( deft != 0 && deft != 1 ) {
- fprintf(stderr, "Error: Parser_getbool given bad default (%d).\n",
- deft);
- assert ( 0 );
- }
- sprintf(theprompt, "%s [%s]: ", prompt, (deft==0)? "N" : "Y");
-
- do {
- line = NULL;
- line = readline(theprompt);
- if ( line == NULL ) {
- result = deft;
- break;
- }
- if ( *line == '\0' ) {
- result = deft;
- break;
- }
- if ( *line == 'y' || *line == 'Y' ) {
- result = 1;
- break;
- }
- if ( *line == 'n' || *line == 'N' ) {
- result = 0;
- break;
- }
- if ( line )
- free(line);
- fprintf(stdout, "Invalid string. Must start with yY or nN\n");
- fflush(stdout);
- } while ( 1 );
-
- if ( line )
- free(line);
- if ( theprompt )
- free(theprompt);
- return result;
-}
-
-/* parse int out of a string or prompt for it */
-long Parser_intarg(const char *inp, const char *prompt, int deft,
- int min, int max, int base)
-{
- long result;
- int rc;
-
- rc = Parser_arg2int(inp, &result, base);
-
- if ( rc == 0 ) {
- return result;
- } else {
- return Parser_getint(prompt, deft, min, max, base);
- }
-}
-
-/* parse int out of a string or prompt for it */
-char *Parser_strarg(char *inp, const char *prompt, const char *deft,
- char *answer, int len)
-{
- if ( inp == NULL || *inp == '\0' ) {
- return Parser_getstr(prompt, deft, answer, len);
- } else
- return inp;
-}
-
-/* change a string into a number: return 0 on success. No invalid characters
- allowed. The processing of base and validity follows strtol(3)*/
-int Parser_arg2int(const char *inp, long *result, int base)
-{
- char *endptr;
-
- if ( (base !=0) && (base < 2 || base > 36) )
- return 1;
-
- *result = strtol(inp, &endptr, base);
-
- if ( *inp != '\0' && *endptr == '\0' )
- return 0;
- else
- return 1;
-}
-
-/* Convert human readable size string to and int; "1k" -> 1000 */
-int Parser_size (int *sizep, char *str) {
- int size;
- char mod[32];
-
- switch (sscanf (str, "%d%1[gGmMkK]", &size, mod)) {
- default:
- return (-1);
-
- case 1:
- *sizep = size;
- return (0);
-
- case 2:
- switch (*mod) {
- case 'g':
- case 'G':
- *sizep = size << 30;
- return (0);
-
- case 'm':
- case 'M':
- *sizep = size << 20;
- return (0);
-
- case 'k':
- case 'K':
- *sizep = size << 10;
- return (0);
-
- default:
- *sizep = size;
- return (0);
- }
- }
-}
-
-/* Convert a string boolean to an int; "enable" -> 1 */
-int Parser_bool (int *b, char *str) {
- if (!strcasecmp (str, "no") ||
- !strcasecmp (str, "n") ||
- !strcasecmp (str, "off") ||
- !strcasecmp (str, "disable"))
- {
- *b = 0;
- return (0);
- }
-
- if (!strcasecmp (str, "yes") ||
- !strcasecmp (str, "y") ||
- !strcasecmp (str, "on") ||
- !strcasecmp (str, "enable"))
- {
- *b = 1;
- return (0);
- }
-
- return (-1);
-}
-
-int Parser_quit(int argc, char **argv)
-{
- argc = argc;
- argv = argv;
- done = 1;
- return 0;
-}
+++ /dev/null
-#ifndef _PARSER_H_
-#define _PARSER_H_
-
-#define HISTORY 100 /* Don't let history grow unbounded */
-#define MAXARGS 100
-
-#define CMD_COMPLETE 0
-#define CMD_INCOMPLETE 1
-#define CMD_NONE 2
-#define CMD_AMBIG 3
-#define CMD_HELP 4
-
-typedef struct parser_cmd {
- char *pc_name;
- int (* pc_func)(int, char **);
- struct parser_cmd * pc_sub_cmd;
- char *pc_help;
-} command_t;
-
-typedef struct argcmd {
- char *ac_name;
- int (*ac_func)(int, char **);
- char *ac_help;
-} argcmd_t;
-
-typedef struct network {
- char *type;
- char *server;
- int port;
-} network_t;
-
-int Parser_quit(int argc, char **argv);
-void Parser_init(char *, command_t *); /* Set prompt and load command list */
-int Parser_commands(void); /* Start the command parser */
-void Parser_qhelp(int, char **); /* Quick help routine */
-int Parser_help(int, char **); /* Detailed help routine */
-void Parser_ignore_errors(int ignore); /* Set the ignore errors flag */
-void Parser_printhelp(char *); /* Detailed help routine */
-void Parser_exit(int, char **); /* Shuts down command parser */
-int Parser_execarg(int argc, char **argv, command_t cmds[]);
-int execute_line(char * line);
-
-/* Converts a string to an integer */
-int Parser_int(char *, int *);
-
-/* Prompts for a string, with default values and a maximum length */
-char *Parser_getstr(const char *prompt, const char *deft, char *res,
- size_t len);
-
-/* Prompts for an integer, with minimum, maximum and default values and base */
-int Parser_getint(const char *prompt, long min, long max, long deft,
- int base);
-
-/* Prompts for a yes/no, with default */
-int Parser_getbool(const char *prompt, int deft);
-
-/* Extracts an integer from a string, or prompts if it cannot get one */
-long Parser_intarg(const char *inp, const char *prompt, int deft,
- int min, int max, int base);
-
-/* Extracts a word from the input, or propmts if it cannot get one */
-char *Parser_strarg(char *inp, const char *prompt, const char *deft,
- char *answer, int len);
-
-/* Extracts an integer from a string with a base */
-int Parser_arg2int(const char *inp, long *result, int base);
-
-/* Convert human readable size string to and int; "1k" -> 1000 */
-int Parser_size(int *sizep, char *str);
-
-/* Convert a string boolean to an int; "enable" -> 1 */
-int Parser_bool(int *b, char *str);
-
-#endif