'unlabeled-1.1.768'.
+++ /dev/null
-.Xrefs
-aclocal.m4
-config.log
-config.status
-config.cache
-configure
-Makefile
-Makefile.in
-.deps
-tags
-TAGS
+++ /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
-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
-
-# NOTE: keep extN before mds
-SUBDIRS = lov utils obdclass ldlm ptlrpc llite lib obdecho mdc osc extN
-SUBDIRS+= mds ost tests obdfilter demos doc scripts
-DIST_SUBDIRS = $(SUBDIRS) obdfs
-EXTRA_DIST = BUGS FDL Rules include patches archdep.m4
-
-# We get the version from the spec file.
-configure: 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
-
+++ /dev/null
-AC_MSG_CHECKING(if you are running user mode linux for $host_alias..)
-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)
-fi
-
-else
- AC_MSG_RESULT(no)
-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
-;;
-
- alpha )
- AC_MSG_RESULT($host_cpu)
- KCFLAGS='-g -O2 -Wall -Wstrict-prototypes -pipe'
- KCPPFLAGS='-D__KERNEL__ -DMODULE '
- MOD_LINK=elf64_alpha
-;;
-
- ia64 )
- AC_MSG_RESULT($host_cpu)
- KCFLAGS='-Wall -Wstrict-prototypes -Wno-trigraphs -g -O2 -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='-Wall -Wstrict-prototypes -Wno-trigraphs -O2 -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='-Wall -Wstrict-prototypes -Wno-trigraphs -O2 -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
+++ /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_ENABLE(linuxdir, [ --enable-linuxdir=[path] set path to Linux source (default=/usr/src/linux)],, enable_linuxdir=$linuxdir_def)
-
-LINUX=$enable_linuxdir
-AC_SUBST(LINUX)
-
-sinclude(archdep.m4)
-
-KINCFLAGS='-I. -I$(top_srcdir)/include -I$(PORTALS)/include -I$(LINUX)/include'
-CPPFLAGS="$KINCFLAGS $ARCHCPPFLAGS"
-
-portalsdir_def='$(top_srcdir)/../portals'
-AC_ARG_ENABLE(portalsdir, [ --enable-portalsdir=[path] set path to Portals source (default=../portals)],, enable_portalsdir=$portalsdir_def)
-PORTALS=$enable_portalsdir
-AC_SUBST(PORTALS)
-
-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 obdfs/Makefile demos/Makefile \
- doc/Makefile scripts/Makefile scripts/lustre.spec \
- extN/Makefile)
+++ /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
-
-demo_SCRIPTS = baseclean.sh basesetup.sh obdfsclean.sh obdfssetup.sh \
- obdtest.sh snap3clean.sh snap3set.sh snapclean.sh snapdel.sh \
- snaprest.sh snaprestclean.sh snapsetup.sh snaptest.sh
-demo_DATA = config.sh
-EXTRA_DIST = $(demo_SCRIPTS) $(demo_DATA)
-
-include $(top_srcdir)/Rules
-
+++ /dev/null
-#!/bin/sh
-# Script to remove the loopback device and temp file created in newtest.sh
-#
-# 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
-
-
-mount | grep "$MNTOBD " > /dev/null 2>&1
-if [ x$? = x0 ]; then
- echo "Stuff still mounted on $MNTOBD"
- exit 1
-fi
-
-mount | grep "$MNTSNAP " > /dev/null 2>&1
-if [ x$? = x0 ]; then
- echo "Stuff still mounted on $MNTSNAP"
- exit 2
-fi
-
-mount | grep "$MNTSNAP2 " > /dev/null 2>&1
-if [ x$? = x0 ]; then
- echo "Stuff still mounted on $MNTSNAP2"
- exit 3
-fi
-
-
-if [ "$LOOPDEV" ]; then
- losetup -d $LOOPDEV
- rmmod loop > /dev/null 2>&1
-fi
-
-if [ "$LOOPDEV" -a "$TMPFILE" -a -f "$TMPFILE" ]; then
- rm -i $TMPFILE
-fi
-
+++ /dev/null
-#! /bin/sh
-# Get the locations for the files from a single place to avoid confusion
-#
-# 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`/.."
-
-# source config info
-. $OBDDIR/demos/config.sh
-
-insmod obdclass
-insmod obdext2
-insmod obdfs
-
-# module configuration
-if [ "$MODCONF" -a -f $MODCONF ]; then
- if [ -z "`grep -i "alias *char-major-$OBDMAJ *obdclass" $MODCONF`" ]; then
- if [ -d /etc/modutils ]; then
- # Debian-style modules configuration.
- echo "alias char-major-${OBDMAJ} obdclass" > /etc/modutils/obd
- update-modules
- else
- echo "alias char-major-${OBDMAJ} obdclass" >>$MODCONF
- fi
- fi
-fi
-
-
-# temp file
-if [ "$LOOPDEV" -a "$TMPFILE" -a -f $TMPFILE ]; then
- echo "$TMPFILE exists; I'm unwilling to overwrite it. Remove [N/y]?" 1>&2
- rm -i $TMPFILE
- [ -f $TMPFILE ] && exit 1
-fi
-[ "$TMPFILE" ] && dd if=/dev/zero of=$TMPFILE bs=1k count=$TMPSIZE
-
-
-# loop device
-if [ "$LOOPDEV" ]; then
- insmod loop > /dev/null 2>&1
- if [ -a "`losetup $LOOPDEV 2> /dev/null`" ]; then
- echo "It appears that $LOOPDEV is in use. Unable to continue" 1>&2
- echo "You need to clean up $LOOPDEV (via cleanup.sh),"
- echo "or you can change which device is used in demos/config.sh" 1>&2
- # undo previous
- [ "$TMPFILE" ] && rm $TMPFILE
- exit 2
- fi
- losetup $LOOPDEV $TMPFILE
-fi
-
-# Ensure that we have the correct devices for OBD to work
-[ ! -c /dev/obd0 ] && mknod /dev/obd0 c $OBDMAJ 0
-[ ! -c /dev/obd1 ] && mknod /dev/obd1 c $OBDMAJ 1
-[ ! -c /dev/obd2 ] && mknod /dev/obd2 c $OBDMAJ 2
-
-
-if [ "$BASEDEV" ]; then
- # echo "No mke2fs!!"
- mke2fs -r 0 -b 4096 $BASEDEV
-else
- echo "\$BASEDEV not defined in demos/config.sh. Please fix!"
- [ "$LOOPDEV" ] && losetup -d $LOOPDEV
- [ "$TMPFILE" ] && rm $TMPFILE
- exit 3
-fi
+++ /dev/null
-#!/bin/sh
-# File which holds configuation parameters in a single place to avoid any
-# mismatch between scripts (especially the cleanup scripts, which are
-# destructive).
-#
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-#set -vx
-
-# Major number for OBD devices
-OBDMAJ=186
-
-# Module configuration file
-[ -f /etc/conf.modules ] && MODCONF=/etc/conf.modules
-[ -z "$MODCONF" -a -f /etc/modules.conf ] && MODCONF=/etc/modules.conf
-
-# If LOOPDEV is empty (""), then no loopback device will be configured.
-# If TMPFILE is empty (""), then no temporary file will be created for loop.
-[ "$TMPFILE" ] || TMPFILE="/tmp/obdfs.tmpfile"
-[ "$TMPSIZE" ] || TMPSIZE=10240
-[ -b /dev/loop/0 ] && LOOPDEV=/dev/loop/0
-[ -z "$LOOPDEV" -a -b /dev/loop0 ] && LOOPDEV="/dev/loop0"
-
-# If LOOPDEV is empty, then it is assumed that BASEDEV is a real block device
-# that doesn't mind being overwritten - don't use a partition with data on it!!
-LOOPDEV="/dev/loop0"
-BASEDEV="/dev/loop0"
-
-# The following are mount points for the filesystems during the test.
-MNTOBD="/mnt/obd"
-MNTSNAP="/mnt/snap"
-MNTSNAP2="/mnt/snap2"
-
-# This is where the snapshot table will be stored:
-SNAPTABLE="/tmp/obdfs.snaptable"
-
-# A simple routine called by most of the scripts to help debugging. The
-# kernel code has a lot of debugging statements, so this helps us keep
-# track of what is going on in user-land to generate the kernel messages.
-plog () {
- if [ "$1" = "log" ]; then
- shift
- logger -p kern.info "******** $* **********"
- echo "$*"
- else
- logger -p kern.info "****start**** $* *****"
- echo "$*"
- $*
- logger -p kern.info "*****end***** $* *****"
- fi
-}
-
-# A routine to display a command, and prompt user if it should be run
-qrun () {
- echo
- echo -n "Run '$*' [Y/n]?'";
- read JUNK
-
- case $JUNK in
- n*|N*) echo "'$*' not run" ;;
- *) plog $* ;;
- esac
-}
+++ /dev/null
-#!/bin/sh
-# Utility script for cleaning up a simple OBDFS mounted filesystem
-#
-# 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
-
-plog umount $MNTOBD
-#killall pupdated # stop the OBDFS flush daemon
-plog rmmod obdfs
-
-plog log "CLEANUP/DETACH"
-$OBDDIR/utils/obdctl << EOF
-device 0
-cleanup
-detach
-quit
-EOF
-
-plog rmmod xfs
-plog rmmod xfs_support
-plog rmmod pagebuf
-plog rmmod obdfilter
-plog rmmod obdext2
-plog rmmod obdclass
-
-$OBDDIR/demos/baseclean.sh
+++ /dev/null
-#! /bin/bash
-# Utility script for configuring a simple OBDFS mount
-#
-# 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
-
-$OBDDIR/demos/basesetup.sh
-
-if [ x$? != x0 ]; then
- echo "Error running basesetup.sh"
- exit 4;
-fi
-
-#insmod $OBDDIR/class/obdclass.o
-#insmod $OBDDIR/ext2obd/obdext2.o
-#insmod $OBDDIR/obdfs/obdfs.o
-
-plog log "ATTACHING device 0 SETUP $BASEDEV"
-$OBDDIR/utils/obdctl << EOF
-device 0
-# attach obdfilter
-# setup $BASEDEV reiserfs
-attach obdext2
-setup $BASEDEV
-quit
-EOF
-
-[ ! -d "$MNTOBD" ] && mkdir $MNTOBD
-plog mount -t obdfs -odevice=/dev/obd0 none $MNTOBD
+++ /dev/null
-#! /bin/bash
-# Utility script to create an OBD snapshot. If an existing filesystem is
-# not already mounted on /mnt/obd, we call the basic OBD setup script to
-# create and mount a filesystem for us.
-#
-# 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
-
-[ ! -d $MNTOBD/lost+found ] && $OBDDIR/demos/obdfssetup.sh
-
-echo "echo yesterday >> $MNTOBD/hello" # create a file
-echo "yesterday" > $MNTOBD/hello
-echo "echo testing > $MNTOBD/goodbye" # create a file
-echo "testing" > $MNTOBD/goodbye
-plog ln -s hello $MNTOBD/link # create a symbolic link
-cd $MNTOBD ; plog touch a b c ; cd - # create a file
+++ /dev/null
-#!/bin/sh
-# Utility script for cleaning up a third snapshot created by setup3.sh
-#
-# 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
-
-plog umount $MNTSNAP2
-
-plog log "CLEANUP /dev/obd3"
-$OBDDIR/utils/obdcontrol -f << EOF
-device /dev/obd3
-cleanup
-detach
-quit
-EOF
-
-$OBDDIR/demos/snapclean.sh
+++ /dev/null
-#!/bin/sh
-# Utility script for creating a third snapshot.
-#
-# 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
-
-[ ! -d $MNTSNAP/lost+found ] && $OBDDIR/demos/snapsetup.sh
-
-$OBDDIR/demos/snaptest.sh
-
-sync
-sleep 5 # let syslog logs get written
-
-plog log "CREATING /dev/obd3 snapshot"
-$OBDDIR/utils/obdcontrol -f << EOF
-snaptable
-$SNAPTABLE
-a
-3
-now
-q
-y
-snapset 0 $SNAPTABLE
-device /dev/obd3
-attach obdsnap 0 3 0
-setup
-quit
-EOF
-
-[ ! -d "$MNTSNAP2" ] && mkdir $MNTSNAP2
-plog mount -t obdfs -oro,device=/dev/obd3 none $MNTSNAP2
+++ /dev/null
-#! /bin/bash
-# Utility script for cleaning up snapshots and removing modules.
-#
-# 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
-
-plog umount $MNTOBD
-plog umount $MNTSNAP
-
-plog log "CLEANUP /dev/obd2 /dev/obd1"
-$OBDDIR/utils/obdcontrol -f << EOF
-device /dev/obd2
-cleanup
-detach
-device /dev/obd1
-cleanup
-detach
-quit
-EOF
-
-rmmod obdsnap
-
-rm $SNAPTABLE
-$OBDDIR/demos/obdfsclean.sh
+++ /dev/null
-#!/bin/sh
-# Utility script to test deleting a snapshot that has been previously
-# created as the setup.sh script does.
-#
-# 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
-
-[ ! -d $MNTSNAP/lost+found ] && echo "need to run obdsetup.sh first" && exit 1
-[ ! -f $MNTOBD/hosts ] && $OBDDIR/demos/snaptest.sh
-
-plog umount $MNTSNAP
-plog umount $MNTOBD
-
-sync
-sleep 1
-plog log "STARTING snapdelete"
-$OBDDIR/utils/obdcontrol -f << EOF
-device /dev/obd2
-connect
-snapdelete
-disconnect
-cleanup
-detach
-snaptable
-$SNAPTABLE
-d
-2
-q
-y
-snapset 0 $SNAPTABLE
-EOF
-plog log "COMPLETE snapdelete"
-plog mount -t obdfs -odevice=/dev/obd1 none $MNTOBD
+++ /dev/null
-#!/bin/sh
-# Utility script to test restoring a previous snapshot. This will destroy
-# the "current" snapshot and restore the old one in its place.
-#
-# 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
-
-[ ! -d $MNTSNAP/lost+found ] && echo "need to run snapsetup.sh first" && exit 1
-
-plog umount $MNTSNAP
-plog umount $MNTOBD
-
-mount | grep "$MNTOBD " > /dev/null 2>&1
-if [ x$? = x0 ]; then
- echo "Stuff still mounted on $MNTOBD; clean up first."
- exit
-fi
-
-mount | grep "$MNTSNAP " > /dev/null 2>&1
-if [ x$? = x0 ]; then
- echo "Stuff still mounted on $MNTSNAP; clean up first."
- exit
-fi
-
-sync
-plog log "STARTING snaprestore"
-
-
-$OBDDIR/utils/obdcontrol -f << EOF
-device /dev/obd1
-cleanup
-detach
-device /dev/obd2
-connect
-snaprestore 2 $SNAPTABLE 0
-quit
-EOF
-
-plog log "COMPLETE snaprestore"
-
-plog mount -t obdfs -odevice=/dev/obd2 none $MNTOBD
+++ /dev/null
-#! /bin/bash
-# Utility script for cleaning up a simple OBDFS mounted filesystem
-#
-# 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
-
-umount $MNTOBD
-mount | grep "$MNTOBD " > /dev/null 2>&1
-if [ x$? = x0 ]; then
- echo "Stuff still mounted on $MNTOBD; clean up first."
- exit
-fi
-
-rmmod obdfs
-
-$OBDDIR/utils/obdcontrol -f << EOF
-device /dev/obd2
-cleanup
-detach
-device /dev/obd0
-cleanup
-detach
-quit
-EOF
-
-rmmod obdsnap
-rmmod obdext2
-rmmod obdclass
-
-rm $SNAPTABLE
-$OBDDIR/demos/baseclean.sh
+++ /dev/null
-#! /bin/bash
-# Utility script to create an OBD snapshot. If an existing filesystem is
-# not already mounted on /mnt/obd, we call the basic OBD setup script to
-# create and mount a filesystem for us.
-#
-# 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
-
-
-# prepare the snapshot drive with a file to be COW'd
-if [ ! -d /mnt/obd/lost+found ]; then
- $OBDDIR/demos/obdfssetup.sh
- if [ x$? != x0 ]; then
- echo "Error running obdfssetup.sh"
- exit 4
- fi
-fi
-
-if [ ! -f $MNTOBD/hello ]; then
- $OBDDIR/demos/obdtest.sh
- if [ x$? != x0 ]; then
- echo "Error in obdfssetup.sh"
- exit 4
- fi
-fi
-
-plog umount $MNTOBD
-
-#plog insmod $OBDDIR/snap/obdsnap.o
-
-rm -f $SNAPTABLE
-
-plog log "NEW SNAP SETUP"
-# Create two snapshots using the OBD snapshot driver. One will be the
-# "current" snapshot (in obd device 1), where changes will take place.
-# The current snapshot is required in order to use the filesystem. The
-# second will be a snapshot of the filesystem taken "now" (in obd device 2)
-# that will remain static (historical read-only) filesystem as changes
-# are made to the current snapshot.
-$OBDDIR/utils/obdcontrol -f << EOF
-snaptable
-$SNAPTABLE
-a
-1
-current
-a
-2
-now
-q
-y
-snapset 0 $SNAPTABLE
-device /dev/obd1
-attach obdsnap 0 1 0
-setup
-device /dev/obd2
-attach obdsnap 0 2 0
-setup
-quit
-EOF
-
-# Mount the two filesystems. The filesystem under $MNTOBD will be the
-# one where changes are made, while $MNTSNAP will contain the original
-# files at the point when the snapshot was taken.
-
-[ ! -d "$MNTOBD" ] && mkdir $MNTOBD
-[ ! -d "$MNTSNAP" ] && mkdir $MNTSNAP
-plog mount -t obdfs -odevice=/dev/obd1 none $MNTOBD
-plog mount -t obdfs -oro,device=/dev/obd2 none $MNTSNAP
+++ /dev/null
-#!/bin/sh
-# Utility script to perform minor modifications to the read-write mounted
-# snapshot in order to demonstrate the changes w.r.t. the read-only snapshot
-#
-# 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
-
-plog chmod 777 $MNTOBD # change attributes on an existing file
-plog rm $MNTOBD/a # delete an existing file
-echo "echo today >> $MNTOBD/hello" # modify an existing file
-echo today >> $MNTOBD/hello
-plog cp /etc/group $MNTOBD # create a new file
-plog ln -s goodbye $MNTOBD/newlink # create a new symlink
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-tags
-TAGS
-OBD-HOWTO.html
-OBD-HOWTO.txt
-lustre-HOWTO.txt
-*.eps
-lustre.lyx
-lustre.pdf
+++ /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 = lyx --export pdf
-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
-IMAGES = sys_open.eps sys_write.eps sys_mount.eps cache1.eps cache2.eps intermezzocache.eps intermezzofilesys.eps meta.eps metadata1.eps networklayer.eps bigpicture.eps intermezzo.eps mds.eps portals.eps client.eps layering.eps metadata.eps sb.eps cow.eps lockacq.eps obdfs.eps snapsetup.eps dirbodyapi.eps loraid.eps ost.eps updates.eps hotmigrate.eps lustreclusters.eps osthw.eps portals-lib.eps lockqueues.eps lockexample1.eps lockexample2.eps lockexample3.eps lockexample4.eps lockseverity.eps
-LYXFILES= lustre.lin evolution.lyx llocks.lyx mgmt.lyx uncertain.lyx\
- fs.lyx lustre-HOWTO.lin namespace.lyx\
- glossary.lyx lustre-debugging.lyx network.lyx\
- intro.lyx obdspec.lyx recovery.lyx
-
-MAINTAINERCLEANFILES = $(IMAGES) $(DOCS) $(VERSIONED)
-CLEANFILES = *.aux *.tex doc.old/*.aux doc.old/*.tex
-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 $(DOCS) $(IMAGES) $(LYXFILES) lustre.bib
-
-all: $(DOCS)
-
-# 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'
-
-# 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.dvi:
- $(LATEX) $<
-
-.dvi.ps:
- $(DVIPS) $< -o $@
-
-.ps.pdf:
- $(PS2PDF) $< $@
-
-lustre.tex lustre.pdf lustre.txt lustre.html: $(IMAGES) 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
-
-lustre-chbar.tex: chbar.sh postbar doc.old/lustre-full.tex lustre-full.tex
- $(SHELL) $(srcdir)/chbar.sh doc.old/lustre-full.tex lustre-full.tex | $(srcdir)/postbar > $@
-
-lustre-full.tex: lustre.tex
- $(TEXEXPAND) -texinputs=. -texinputs=$(srcdir) -output=$@ $<
-
-doc.old/lustre.tex: doc.old/lustre-HOWTO.lyx
-doc.old/lustre-full.tex: doc.old/lustre.tex
- cd doc.old && $(TEXEXPAND) -texinputs=. -output=lustre-full.tex lustre.tex
-
-# 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
---------
-
-For even minor releases a branch tag will be created. The branch tag
-will be of the form:
-
-bmajor_minor
-
-Note that the CVS head is where development is going. If developers
-use a branch they must eventually merge that back into the head.
-Typically this is done by importing changes into the branch and
-removing the sticky tags:
-
-cvs update -A
-
-fixing any conflicts and then committing.
+++ /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
-.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
+++ /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
-
-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
-EXTN_EXTRA = include/linux/xattr.h include/linux/extN_xattr.h fs/extN/xattr.c fs/extN/hash.c
-extN_SOURCES = $(EXTNC) xattr.c # punch.c
-extN_DEPENDENCIES = patch-stamp
-EXTRA_DIST = $(EXTNP) extN-2.4.18-ino_sb_fixup.diff extN-2.4.18-exports.diff
-DISTCLEANFILES = $(extN_SOURCES) patch-stamp *.orig *.rej
-SUB=-e "s/ext3/extN/g" -e "s/EXT3/EXTN/g"
-
-include $(top_srcdir)/Rules
-
-# Create a fresh ext2 patch.
-diff:
- $(RM) extN.patchT
- for f in $(EXTNC); do diff -u $(top_srcdir)/fs/extN/$$f $$f >> extN.patchT ; done
- mv -f ext2.patchT $(srcdir)/ext2.patch-$(RELEASE)
-.PHONY: diff
-
-# 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).
-patch-stamp: $(EXTNP)
- $(RM) $@
- test -e $(top_srcdir)/fs || ln -sf . $(top_srcdir)/fs
- set -vx;\
- list='$(EXTN_EXTRA)'; for f in $$list; do $(RM) $(top_srcdir)/$$f; done
- set -vx;\
- list='$(EXTNC)'; for f in $$list; do \
- sed $(SUB) $(LINUX)/fs/ext3/$$f > $(top_srcdir)/fs/extN/$$f; \
- done
- set -vx;\
- list='$(EXTNI)'; for i in $$list; do \
- s=`echo $$i | sed "s/extN/ext3/"`; \
- sed $(SUB) $(LINUX)/include/linux/$$s > \
- $(top_srcdir)/include/linux/$$i; \
- done
- set -vx;\
- if [ -f $(srcdir)/extN.patch-$(RELEASE) ]; then \
- patch -p0 < $(srcdir)/extN.patch-$(RELEASE); \
- else \
- list='$(EXTNP)'; for p in $$list; do \
- sed $(SUB) $(srcdir)/$$p|(cd $(top_srcdir);patch -p1)||exit -1;\
- done; \
- echo "It is OK if the following patch fails"; \
- (cd $(top_srcdir); patch -N -p1) < $(srcdir)/extN-2.4.18-exports.diff; \
- (cd $(top_srcdir); patch -p1) < $(srcdir)/extN-2.4.18-ino_sb_fixup.diff; \
- 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
---- ./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,8 +273,9 @@ void ext3_free_blocks (handle_t *handle,
- return;
- }
- lock_super (sb);
-- es = sb->u.ext3_sb.s_es;
-- if (block < le32_to_cpu(es->s_first_data_block) ||
-+ 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)) {
- ext3_error (sb, "ext3_free_blocks",
- "Freeing blocks not in datazone - "
-@@ -304,22 +303,11 @@ 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;
-
-- 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.
-@@ -340,19 +328,29 @@ 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;
-
-- 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),
-+ EXT3_SB(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 +363,8 @@ do_more:
- #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++;
-@@ -410,12 +407,11 @@ 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) {
-- block += count;
- count = overflow;
- goto do_more;
- }
-@@ -564,17 +560,18 @@ 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;
-
- ext3_debug ("goal=%lu.\n", goal);
-
-+repeat:
- /*
- * First, test whether the goal block is free.
- */
-@@ -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)
-@@ -684,10 +681,21 @@ got_block:
- 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! */
-@@ -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++) {
- /*
-@@ -1015,8 +1018,8 @@ static int ext3_prepare_write(struct fil
- 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);
-@@ -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;
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, 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>
-@@ -38,6 +42,432 @@
- #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)
-+ {
-+ map[count].hash = dx_hash (de->name, de->name_len);
-+ map[count].offs = (u32) ((char *) de - base);
-+ de = (ext3_dirent *) ((char *) de + le16_to_cpu(de->rec_len));
-+ count++;
-+ }
-+ 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,88 @@
- 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[MAX_DX_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;
-+
-+ 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));
-+ 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;
-- ext3_mark_inode_dirty(handle, dir);
-- dir->i_version = ++event;
-- 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>
-@@ -466,6 +467,8 @@
- inode->i_mapping->a_ops = &ext3_aops;
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ if (err)
-+ ext3_xattr_drop_inode(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -491,6 +494,8 @@
- init_special_inode(inode, mode, rdev);
- ext3_mark_inode_dirty(handle, inode);
- err = ext3_add_nondir(handle, dentry, inode);
-+ if (err)
-+ ext3_xattr_drop_inode(handle, inode);
- }
- ext3_journal_stop(handle, dir);
- return err;
-@@ -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
+++ /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.
- *
- */
-
-#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);
-#endif
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- */
-
-#ifndef _LUSTRE_DLM_H__
-#define _LUSTRE_DLM_H__
-
-#ifdef __KERNEL__
-
-#include <linux/proc_fs.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_net.h>
-
-#define OBD_LDLM_DEVICENAME "ldlm"
-
-typedef enum {
- ELDLM_OK = 0,
-
- ELDLM_LOCK_CHANGED = 300,
- ELDLM_LOCK_ABORTED = 301,
- ELDLM_RESOURCE_FREED = 302,
-
- 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)
-#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)
-#define LDLM_FL_AST_SENT (1 << 5)
-#define LDLM_FL_DESTROYED (1 << 6)
-#define LDLM_FL_WAIT_NOREPROC (1 << 7)
-
-#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;
- struct ptlrpc_client ns_rpc_client;/* used for revocation callbacks */
- __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;
-};
-
-/*
- *
- * 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);
-
-typedef int (*ldlm_completion_callback)(struct ldlm_lock *lock, int flags);
-
-struct ldlm_lock {
- __u64 l_random;
- int 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_res_link; /*position in one of three res lists*/
-
- 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 ptlrpc_connection *l_connection;
- struct ptlrpc_client *l_client;
- struct lustre_handle *l_connh;
- __u32 l_flags;
- struct lustre_handle l_remote_handle;
- void *l_data;
- __u32 l_data_len;
- void *l_cookie;
- int l_cookie_len;
- struct ldlm_extent l_extent;
- __u32 l_version[RES_VERSION_SIZE];
-
- __u32 l_readers;
- __u32 l_writers;
-
- /* 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, void *data);
-
-#define LDLM_PLAIN 10
-#define LDLM_EXTENT 11
-#define LDLM_MDSINTENT 12
-
-#define LDLM_MIN_TYPE 10
-#define LDLM_MAX_TYPE 12
-
-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; /* PLAIN, EXTENT, or MDSINTENT */
- 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;
-};
-
-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 \
- " (UNKNOWN: lock %p(rc=%d/%d,%d) mode %s/%s on " \
- "res \?\? (rc=\?\?) type \?\?\? remote %Lx)\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); \
- else \
- CDEBUG(D_DLMTRACE, "### " format \
- " (%s: lock %p(rc=%d/%d,%d) mode %s/%s on res " \
- "%Lu (rc=%d) type %s remote %Lx)\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], \
- 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)
-
-/* ldlm_extent.c */
-int ldlm_extent_compat(struct ldlm_lock *, struct ldlm_lock *);
-int ldlm_extent_policy(struct ldlm_lock *, void *, ldlm_mode_t, 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);
-
-/* ldlm_lock.c */
-void ldlm_register_intent(int (*arg)(struct ldlm_lock *lock, void *req_cookie,
- ldlm_mode_t mode, 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 *handle);
-void ldlm_lock2handle(struct ldlm_lock *lock, struct lustre_handle *lockh);
-
-#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; \
-})
-
-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_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, int count);
-int ldlm_regression_stop(void);
-
-
-/* resource.c */
-struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 local);
-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_put(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);
-
-/* 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);
-
-#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:
- */
-
-#ifndef _LUSTRE_HA_H
-#define _LUSTRE_HA_H
-
-#include <linux/lustre_net.h>
-
-#define LUSTRE_HA_NAME "ptlrpc"
-
-extern struct recovd_obd *ptlrpc_connmgr;
-
-struct connmgr_thread {
- struct recovd_obd *mgr;
- char *name;
-};
-
-int connmgr_connect(struct recovd_obd *mgr, struct ptlrpc_connection *conn);
-int connmgr_handle(struct ptlrpc_request *req);
-void recovd_cli_fail(struct ptlrpc_client *cli);
-void recovd_cli_manage(struct recovd_obd *mgr, struct ptlrpc_client *cli);
-void recovd_cli_fixed(struct ptlrpc_client *cli);
-int recovd_setup(struct recovd_obd *mgr);
-int recovd_cleanup(struct recovd_obd *mgr);
-
-#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 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_REQUEST_PORTAL 15
-#define LDLM_REPLY_PORTAL 16
-#define LDLM_CLI_REQUEST_PORTAL 17
-#define LDLM_CLI_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 RECOVD_STOPPING 1 /* how cleanup tells recovd to quit */
-#define RECOVD_IDLE 2 /* normal state */
-#define RECOVD_STOPPED 4 /* after recovd has stopped */
-#define RECOVD_FAIL 8 /* RPC timeout: wakeup recovd, sets flag */
-#define RECOVD_TIMEOUT 16 /* set when recovd detects a timeout */
-#define RECOVD_UPCALL_WAIT 32 /* an upcall has been placed */
-#define RECOVD_UPCALL_ANSWER 64 /* an upcall has been answered */
-
-#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_OK 0
-
-#define PTL_RPC_TYPE_REQUEST 2
-#define PTL_RPC_TYPE_REPLY 3
-
-#define PTLRPC_MSG_MAGIC (cpu_to_le32(0x0BD00BD0))
-#define PTLRPC_MSG_VERSION (cpu_to_le32(0x00040001))
-
-struct lustre_handle {
- __u64 addr;
- __u64 cookie;
-};
-
-/* 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 buflens[0];
-};
-
-#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_stripe_md {
- __u32 lmd_magic;
- __u32 lmd_easize; /* packed size of extended */
- __u64 lmd_object_id; /* lov object id */
- __u64 lmd_stripe_offset; /* offset of the stripe */
- __u64 lmd_stripe_size; /* size of the stripe */
- __u32 lmd_stripe_count; /* how many objects are being striped */
- __u32 lmd_stripe_pattern; /* per-lov object stripe pattern */
- struct lov_object_id lmd_objects[0];
-};
-
-#define OBD_MD_FLALL (0xffffffff)
-#define OBD_MD_FLID (0x00000001)
-#define OBD_MD_FLATIME (0x00000002)
-#define OBD_MD_FLMTIME (0x00000004)
-#define OBD_MD_FLCTIME (0x00000008)
-#define OBD_MD_FLSIZE (0x00000010)
-#define OBD_MD_FLBLOCKS (0x00000020)
-#define OBD_MD_FLBLKSZ (0x00000040)
-#define OBD_MD_FLMODE (0x00000080)
-#define OBD_MD_FLTYPE (0x00000100)
-#define OBD_MD_FLUID (0x00000200)
-#define OBD_MD_FLGID (0x00000400)
-#define OBD_MD_FLFLAGS (0x00000800)
-#define OBD_MD_FLOBDFLG (0x00001000)
-#define OBD_MD_FLNLINK (0x00002000)
-#define OBD_MD_FLGENER (0x00004000)
-#define OBD_MD_FLINLINE (0x00008000)
-#define OBD_MD_FLRDEV (0x00010000)
-#define OBD_MD_FLEASIZE (0x00020000)
-#define OBD_MD_LINKNAME (0x00040000)
-#define OBD_MD_FLNOTOBD (~(OBD_MD_FLOBDFLG | OBD_MD_FLBLOCKS | OBD_MD_LINKNAME))
-
-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
-
-struct obd_ioobj {
- obd_id ioo_id;
- obd_gr ioo_gr;
- __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;
- __u8 conn_uuid[37];
-};
-
-/* 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_RECREATE 6
-#define REINT_MAX 6
-
-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;
- __u64 size;
- __u64 extra;
- __u32 valid;
- __u32 mode;
- __u32 uid;
- __u32 gid;
- __u32 mtime;
- __u32 ctime;
- __u32 atime;
- __u32 flags;
- __u32 major;
- __u32 minor;
- __u32 ino;
- __u32 nlink;
- __u32 generation;
- __u32 last_xidnomore;
-};
-
-/* MDS update records */
-
-
-//struct mds_update_record_hdr {
-// __u32 ur_opcode;
-//};
-
-struct mds_rec_setattr {
- __u32 sa_opcode;
- __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_mode;
- struct ll_fid cr_fid;
- __u32 cr_uid;
- __u32 cr_gid;
- __u64 cr_time;
- __u64 cr_rdev;
-};
-
-struct mds_rec_link {
- __u32 lk_opcode;
- __u32 lk_reserved;
- struct ll_fid lk_fid1;
- struct ll_fid lk_fid2;
-};
-
-struct mds_rec_unlink {
- __u32 ul_opcode;
- __u32 ul_mode;
- struct ll_fid ul_fid1;
- struct ll_fid ul_fid2;
-};
-
-struct mds_rec_rename {
- __u32 rn_opcode;
- __u32 rn_reserved;
- 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_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 */
- 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. <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/portals_lib.h>
-#include <linux/lustre_idl.h>
-
-#ifdef __KERNEL__
-/* l_net.c */
-struct ptlrpc_request;
-struct obd_device;
-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,
- char *cluuid);
-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);
-
-/* 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 *);
-
-
-/* page.c */
-#define CB_PHASE_START 12
-#define CB_PHASE_FINISH 13
-struct io_cb_data {
- wait_queue_head_t waitq;
- atomic_t refcount;
- int complete;
- int err;
- struct ptlrpc_bulk_desc *desc;
-};
-int ll_sync_io_cb(struct io_cb_data *data, int err, int phase);
-struct io_cb_data *ll_init_cb(void);
-inline void lustre_put_page(struct page *page);
-struct page *lustre_get_page_read(struct inode *dir, unsigned long index);
-struct page *lustre_get_page_write(struct inode *dir, unsigned long index);
-int lustre_commit_write(struct page *page, unsigned from, unsigned to);
-void set_page_clean(struct page *page);
-void set_page_dirty(struct page *page);
-
-/* simple.c */
-struct obd_run_ctxt;
-void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new);
-void pop_ctxt(struct obd_run_ctxt *saved);
-#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 dentry *simple_mkdir(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);
- 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 obd_statfs_pack(struct obd_statfs *osfs, struct statfs *sfs);
-void obd_statfs_unpack(struct obd_statfs *osfs, struct statfs *sfs);
-
-#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 && obd_ioctl_packlen(data) > 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;
-}
-
-#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_CONFIG _IOWR('f', 132, long)
-
-#define OBD_IOC_DEC_FS_USE_COUNT _IO ('f', 133 )
-
-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(signals, cb, data) \
-((struct l_wait_info) { \
- lwi_signals: signals, \
- lwi_on_signal: cb, \
- lwi_cb_data: data \
-})
-
-#define LWI_TIMEOUT_INTR(time, time_cb, signals, sig_cb, data) \
-((struct l_wait_info) { \
- lwi_timeout: time, \
- lwi_on_timeout: time_cb, \
- lwi_signals: signals, \
- 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; \
- init_waitqueue_entry(&__wait, current); \
- \
- add_wait_queue(&wq, &__wait); \
- __state = TASK_UNINTERRUPTIBLE; \
- for (;;) { \
- set_current_state(__state); \
- if (condition) \
- break; \
- /* We only become INTERRUPTIBLE if a timeout has fired, and \
- * the caller has given us some signals to care about. \
- * \
- * XXXshaver we should check against info->wli_signals here, \
- * XXXshaver instead of just using l_killable_pending, perhaps. \
- */ \
- 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) { \
- if (schedule_timeout(info->lwi_timeout) == 0) { \
- /* We'll take signals only after a timeout. */ \
- if (info->lwi_signals) \
- __state = TASK_INTERRUPTIBLE; \
- if (info->lwi_on_timeout && \
- info->lwi_on_timeout(info->lwi_cb_data)) { \
- ret = -ETIMEDOUT; \
- 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
- *
- *
- *
-
-
-
-#ifndef _LL_H
-#define _LL_H
-
-#include <linux/fs.h>
-#include <linux/ext2_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 {
- __u64 fd_mdshandle;
- struct ptlrpc_request *fd_req;
- __u32 fd_flags;
-};
-
-struct ll_inode_md {
- struct mds_body *body;
- struct lov_stripe_md *md;
-};
-
-#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_FILE_IGNORE_LOCK 0x00000001
-
-#define LL_INLINESZ 60
-struct ll_inode_info {
- struct lov_stripe_md *lli_smd;
- char *lli_symlink_name;
- struct lustre_handle lli_intent_lock_handle;
- struct semaphore lli_open_sem;
-};
-
-#define LL_SUPER_MAGIC 0x0BD00BD0
-
-#define LL_COMMITCBD_STOPPING 0x1
-#define LL_COMMITCBD_STOPPED 0x2
-#define LL_COMMITCBD_RUNNING 0x4
-
-struct ll_sb_info {
- struct lustre_handle ll_mdc_conn;
- struct lustre_handle ll_osc_conn;
- obd_id ll_rootino; /* number of root inode */
-
- 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;
-};
-
-
-static inline struct ll_sb_info *ll_s2sbi(struct super_block *sb)
-{
- return (struct ll_sb_info *)(sb->u.generic_sbp);
-}
-
-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;
-}
-
-static inline struct ll_sb_info *ll_i2sbi(struct inode *inode)
-{
- return ll_s2sbi(inode->i_sb);
-}
-
-static inline struct ll_inode_info *ll_i2info(struct inode *inode)
-{
- return (struct ll_inode_info *)&(inode->u.generic_ip);
-}
-
-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);
-}
-
-/* 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);
-
-/* dcache.c */
-void ll_intent_release(struct dentry *de);
-
-/* 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;
-
-/* rw.c */
-struct page *ll_getpage(struct inode *inode, unsigned long offset,
- int create, int locked);
-void ll_truncate(struct inode *inode);
-
-/* 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
+++ /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/lustre_idl.h>
-#include <linux/lustre_net.h>
-
-struct ldlm_lock_desc;
-struct lov_stripe_md;
-
-#define LUSTRE_MDS_NAME "mds"
-#define LUSTRE_MDC_NAME "mdc"
-
-struct mds_update_record {
- __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 */
- __u32 mcd_last_xid; /* client RPC xid for the last transaction */
- __u8 padding[MDS_LR_SIZE - 60];
-};
-
-/* In-memory access to client data from MDS struct */
-struct mds_export_data {
- struct list_head med_open_head;
- 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 file * mfd_file;
- __u64 mfd_clientfd;
- __u32 mfd_clientcookie;
-};
-
-/* 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_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_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 *,
- __u32 mode, __u64 id, __u32 uid, __u32 gid, __u64 time,
- const char *name, int namelen, const char *tgt,
- int tgtlen);
-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(int offset, struct ptlrpc_request *req);
-
-/* mdc/mdc_request.c */
-extern int mdc_con2cl(struct lustre_handle *conn, struct ptlrpc_client **cl,
- struct ptlrpc_connection **connection,
- struct lustre_handle **rconn);
-
-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 *h, __u64 id,
- char *tgt, int tgtlen, void *data, int datalen);
-int mdc_getlovinfo(struct obd_device *obd, struct lustre_handle *mdc_connh,
- uuid_t **uuids, struct ptlrpc_request **request);
-int mdc_getstatus(struct lustre_handle *conn,
- struct ll_fid *rootfid, __u64 *last_committed,
- __u32 *last_xid, struct ptlrpc_request **);
-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_statfs(struct lustre_handle *conn,
- struct statfs *sfs, 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_stripe_md *, __u64 cookie, __u64 *fh,
- struct ptlrpc_request **);
-int mdc_close(struct lustre_handle *conn,
- obd_id ino, int type, __u64 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 char *tgt, int tgtlen, int mode, __u32 uid, __u32 gid,
- __u64 time, __u64 rdev, struct lov_stripe_md *md,
- 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(char *uuid, struct ptlrpc_client *cl);
-
-extern int mds_client_add(struct mds_export_data *med, int cl_off);
-extern int mds_client_free(struct mds_export_data *med);
-
-/* 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_stripe_md *md);
- int (* fs_get_md)(struct inode *inode,
- struct lov_stripe_md *md);
- 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);
-
-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)
-{
- /*
- * 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.
- */
- return mds->mds_fsops->fs_setattr(dentry, handle, iattr);
-}
-
-static inline int mds_fs_set_md(struct mds_obd *mds, struct inode *inode,
- void *handle, struct lov_stripe_md *md)
-{
- return mds->mds_fsops->fs_set_md(inode, handle, md);
-}
-
-static inline int mds_fs_get_md(struct mds_obd *mds, struct inode *inode,
- struct lov_stripe_md *md)
-{
- return mds->mds_fsops->fs_get_md(inode, md);
-}
-
-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);
-}
-
-#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>
-
-/* default rpc ring length */
-#define RPC_RING_LENGTH 10
-
-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];
-
- int c_level;
- __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;
- __u32 c_xid_in;
- __u32 c_xid_out;
-
- atomic_t c_refcount;
- __u64 c_token;
- __u64 c_remote_conn;
- __u64 c_remote_token;
-};
-
-struct ptlrpc_client {
- struct obd_device *cli_obd;
- __u32 cli_request_portal;
- __u32 cli_reply_portal;
-
- __u64 cli_last_xid;
- __u64 cli_last_committed;
- __u32 cli_target_devno;
-
- void *cli_data;
- struct semaphore cli_rpc_sem; /* limits outstanding requests */
-
- spinlock_t cli_lock; /* protects lists */
- struct list_head cli_delayed_head; /* delayed until after recovery */
- struct list_head cli_sending_head;
- struct list_head cli_dying_head;
- struct list_head cli_ha_item;
- int (*cli_recover)(struct ptlrpc_client *);
-
- struct recovd_obd *cli_recovd;
- 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_RECOVERY (1 << 8) /* retransmission for recovery */
-#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_REQUEST, PTL_RPC_REPLY, PTL_RPC_BULK */
- struct list_head rq_list;
- struct list_head rq_multi;
- struct obd_device *rq_obd;
- int rq_status;
- int rq_flags;
- __u32 rq_connid;
- atomic_t rq_refcount;
-
- int rq_reqlen;
- struct lustre_msg *rq_reqmsg;
-
- int rq_replen;
- struct lustre_msg *rq_repmsg;
- __u64 rq_transno;
- __u64 rq_xid;
-
- char *rq_bulkbuf;
- int rq_bulklen;
-
- int rq_level;
- time_t rq_time;
- 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_md_t rq_reply_md_h;
- ptl_handle_me_t rq_reply_me_h;
-
- /* outgoing req/rep */
- ptl_md_t rq_req_md;
- ptl_handle_md_t rq_req_md_h;
-
- 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 ptlrpc_client *rq_client;
- struct ptlrpc_service *rq_svc;
-};
-
-struct ptlrpc_bulk_page {
- struct ptlrpc_bulk_desc *b_desc;
- struct list_head b_link;
- char *b_buf;
- int b_buflen;
- struct page *b_page;
- __u32 b_xid;
- __u32 b_flags;
- struct dentry *b_dentry;
- int (*b_cb)(struct ptlrpc_bulk_page *);
-};
-
-struct ptlrpc_bulk_desc {
- int b_flags;
- struct ptlrpc_connection *b_connection;
- struct ptlrpc_client *b_client;
- __u32 b_portal;
- struct lustre_handle b_conn;
- void (*b_cb)(struct ptlrpc_bulk_desc *, void *);
- void *b_cb_data;
-
- wait_queue_head_t b_waitq;
- struct list_head b_page_list;
- __u32 b_page_count;
- atomic_t b_refcount;
- void *b_desc_private;
- struct tq_struct b_queue;
-
- ptl_md_t b_md;
- ptl_handle_md_t b_md_h;
- ptl_handle_me_t b_me_h;
-
- struct iovec b_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_service {
- time_t srv_time;
- time_t srv_timeout;
-
- /* incoming request buffers */
- /* FIXME: perhaps a list of EQs, if multiple NIs are used? */
- char *srv_buf[RPC_RING_LENGTH];
- __u32 srv_ref_count[RPC_RING_LENGTH];
- ptl_handle_me_t srv_me_h[RPC_RING_LENGTH];
- __u32 srv_buf_size;
- __u32 srv_ring_length;
- __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_reqs;
- struct list_head srv_threads;
- int (*srv_handler)(struct ptlrpc_request *req);
-};
-
-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;
-}
-struct ptlrpc_request *ptlrpc_prep_req2(struct lustre_handle *conn,
- int opcode, int count, int *lengths,
- char **bufs);
-
-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 *conn, char *uuid);
-struct ptlrpc_connection *ptlrpc_get_connection(struct lustre_peer *peer);
-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);
-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_service *service, int i);
-
-/* rpc/client.c */
-void ptlrpc_init_client(struct recovd_obd *,
- int (*recover)(struct ptlrpc_client *),
- int req_portal, int rep_portal,
- struct ptlrpc_client *);
-void ptlrpc_cleanup_client(struct ptlrpc_client *cli);
-__u8 *ptlrpc_req_to_uuid(struct ptlrpc_request *req);
-struct ptlrpc_connection *ptlrpc_uuid_to_connection(char *uuid);
-
-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 ptlrpc_client *cl,
- struct ptlrpc_connection *u, 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);
-int ptlrpc_check_status(struct ptlrpc_request *req, int err);
-
-/* rpc/service.c */
-struct ptlrpc_service *
-ptlrpc_init_svc(__u32 bufsize, int req_portal, int rep_portal, char *uuid,
- svc_handler_t);
-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->b_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->b_refcount));
- }
-}
-
-static inline void ptlrpc_bulk_addref(struct ptlrpc_bulk_desc *desc)
-{
- atomic_inc(&desc->b_refcount);
- CDEBUG(D_PAGE, "Set refcount of %p to %d\n", desc,
- atomic_read(&desc->b_refcount));
-}
-
-#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 __OBD_H
-#define __OBD_H
-#include <linux/fs.h>
-#include <linux/list.h>
-#include <linux/smp_lock.h>
-#include <linux/proc_fs.h>
-
-#include <linux/lustre_idl.h>
-
-struct obd_type {
- struct list_head typ_chain;
- struct obd_ops *typ_ops;
- char *typ_name;
- int typ_refcnt;
-};
-
-struct io_cb_data;
-typedef int (*brw_callback_t)(struct io_cb_data *, int err, int phase);
-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;
-};
-
-#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;
-#ifdef OBD_CTXT_DEBUG
- __u32 magic;
-#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_lock;
- __u64 fo_lastino;
- struct file_operations *fo_fop;
- struct inode_operations *fo_iop;
- struct address_space_operations *fo_aops;
-};
-
-struct mds_server_data;
-
-struct client_obd {
- struct ptlrpc_client *cl_client;
- struct ptlrpc_client *cl_ldlm_client;
- struct ptlrpc_connection *cl_conn;
- struct lustre_handle cl_exporth;
- struct semaphore cl_sem;
- int cl_conn_count;
- __u8 cl_target_uuid[37];
- int cl_max_mdsize;
-};
-
-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;
- __u64 mds_last_committed;
- __u64 mds_last_rcvd;
- __u64 mds_mount_count;
- struct ll_fid mds_rootfid;
- struct mds_server_data *mds_server_data;
-};
-
-struct ldlm_obd {
- struct ptlrpc_service *ldlm_service;
- struct ptlrpc_client *ldlm_client;
- struct ptlrpc_connection *ldlm_server_conn;
-};
-
-struct echo_obd {
- char *eo_fstype;
- struct super_block *eo_sb;
- struct vfsmount *eo_vfsmnt;
- struct obd_run_ctxt eo_ctxt;
- spinlock_t eo_lock;
- __u64 eo_lastino;
- struct file_operations *eo_fop;
- struct inode_operations *eo_iop;
- struct address_space_operations *eo_aops;
-};
-
-struct recovd_obd {
- time_t recovd_waketime;
- time_t recovd_timeout;
- struct ptlrpc_service *recovd_service;
- struct ptlrpc_client *recovd_client;
- __u32 recovd_flags;
- __u32 recovd_wakeup_flag;
- spinlock_t recovd_lock;
- struct list_head recovd_clients_lh; /* clients managed */
- struct list_head recovd_troubled_lh; /* clients in trouble */
- 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;
-};
-
-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 lov_tgt_desc {
- uuid_t uuid;
- struct lustre_handle conn;
-};
-
-struct lov_obd {
- struct obd_device *mdcobd;
- struct lov_desc desc;
- int bufsize;
- 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;
- __u8 obd_uuid[37];
-
- 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;
- union {
- struct ext2_obd ext2;
- struct filter_obd filter;
- struct mds_obd mds;
- struct client_obd cli;
- struct ost_obd ost;
- // 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;
-};
-
-struct io_cb_data;
-
-struct obd_ops {
- int (*o_iocontrol)(long 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,
- char *cluuid);
- int (*o_disconnect)(struct lustre_handle *conn);
-
-
- int (*o_statfs)(struct lustre_handle *conn, struct statfs *statfs);
- 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 *);
- int (*o_close)(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *);
- int (*o_brw)(int rw, struct lustre_handle *conn,
- struct lov_stripe_md *md, obd_count oa_bufs,
- struct brw_page *pgarr, brw_callback_t callback,
- struct io_cb_data *data);
- int (*o_punch)(struct lustre_handle *conn, struct obdo *tgt,
- struct lov_stripe_md *md, 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 *);
-};
-
-#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 __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>
-#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
-
-extern struct proc_dir_entry *
-proc_lustre_register_obd_device(struct obd_device *obd);
-extern void proc_lustre_release_obd_device(struct obd_device *obd);
-extern void proc_lustre_remove_obd_entry(const char* name,
- struct obd_device *obd);
-
-/*
- * ======== OBD Operations Declarations ===========
- */
-
-#ifdef __KERNEL__
-extern struct obd_export *class_conn2export(struct lustre_handle *conn);
-extern struct obd_device *class_conn2obd(struct lustre_handle *conn);
-extern int class_rconn2export(struct lustre_handle *conn,
- struct lustre_handle *rconn);
-
-struct obd_export {
- __u64 exp_cookie;
- struct lustre_handle exp_rconnh; /* remote connection handle */
- struct lustre_handle exp_impconnh;
- struct list_head exp_chain;
- struct obd_device *exp_obd;
- struct ptlrpc_connection *exp_connection;
- struct mds_export_data exp_mds_data;
-#if NOTYET && 0
- struct ldlm_export_data exp_ldlm_data;
- struct ost_export_data exp_ost_data;
-#endif
- void *exp_data; /* device specific data */
- int exp_desclen;
- char *exp_desc;
- uuid_t exp_uuid;
-};
-
-struct obd_import {
- __u64 imp_cookie;
- struct lustre_handle imp_expconnh;
- struct list_head imp_chain;
- struct obd_device *imp_obd;
- unsigned int imp_id;
- void *imp_data; /* device specific data */
-};
-
-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, export) \
-do { \
- if (!(conn)) { \
- CERROR("NULL connection\n"); \
- RETURN(-EINVAL); \
- } \
- \
- export = class_conn2export(conn); \
- if (!(export)) { \
- CERROR("No export\n"); \
- RETURN(-EINVAL); \
- } \
- \
- if (!((export)->exp_obd->obd_flags & OBD_SET_UP)) { \
- CERROR("Device %d not setup\n", \
- (export)->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)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,get_info);
-
- rc = OBP(export->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)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,set_info);
-
- rc = OBP(export->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;
-
- 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;
-
- OBD_CHECK_DEVSETUP(obd);
- OBD_CHECK_OP(obd,cleanup);
-
- rc = OBP(obd, cleanup)(obd);
- RETURN(rc);
-}
-
-static inline int obd_create(struct lustre_handle *conn, struct obdo *obdo, struct lov_stripe_md **ea)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,create);
-
- rc = OBP(export->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)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,destroy);
-
- rc = OBP(export->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)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,getattr);
-
- rc = OBP(export->exp_obd, getattr)(conn, obdo, ea);
- RETURN(rc);
-}
-
-static inline int obd_close(struct lustre_handle *conn, struct obdo *obdo, struct lov_stripe_md *md)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,close);
-
- rc = OBP(export->exp_obd, close)(conn, obdo, md);
- RETURN(rc);
-}
-static inline int obd_open(struct lustre_handle *conn, struct obdo *obdo,
- struct lov_stripe_md *md)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,open);
-
- rc = OBP(export->exp_obd, open) (conn, obdo, md);
- RETURN(rc);
-}
-
-static inline int obd_setattr(struct lustre_handle *conn,
- struct obdo *obdo,
- struct lov_stripe_md *ea)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,setattr);
-
- rc = OBP(export->exp_obd, setattr)(conn, obdo, ea);
- RETURN(rc);
-}
-
-static inline int obd_connect(struct lustre_handle *conn, struct obd_device *obd,
- char *cluuid)
-{
- int rc;
- OBD_CHECK_DEVSETUP(obd);
- OBD_CHECK_OP(obd,connect);
-
- rc = OBP(obd, connect)(conn, obd, cluuid);
- RETURN(rc);
-}
-
-static inline int obd_disconnect(struct lustre_handle *conn)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,disconnect);
-
- rc = OBP(export->exp_obd, disconnect)(conn);
- RETURN(rc);
-}
-
-static inline int obd_statfs(struct lustre_handle *conn, struct statfs *buf)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,statfs);
-
- rc = OBP(export->exp_obd, statfs)(conn, buf);
- RETURN(rc);
-}
-
-static inline int obd_punch(struct lustre_handle *conn, struct obdo *tgt,
- struct lov_stripe_md *md,
- obd_size count, obd_off offset)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,punch);
-
- rc = OBP(export->exp_obd, punch)(conn, tgt, md, count, offset);
- RETURN(rc);
-}
-
-static inline int obd_brw(int cmd, struct lustre_handle *conn,
- struct lov_stripe_md *md,
- obd_count oa_bufs,
- struct brw_page *pg,
- brw_callback_t callback, void *data)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->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(export->exp_obd, brw)(cmd, conn, md, oa_bufs, pg, callback, data);
- 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)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,preprw);
-
- rc = OBP(export->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)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,commitrw);
-
- rc = OBP(export->exp_obd, commitrw)(cmd, conn, objcount, obj, niocount,
- local, desc_private);
- RETURN(rc);
-}
-
-static inline int obd_iocontrol(int cmd, struct lustre_handle *conn,
- int len, void *karg, void *uarg)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,iocontrol);
-
- rc = OBP(export->exp_obd, iocontrol)(cmd, conn, len, karg, uarg);
- RETURN(rc);
-}
-
-static inline int obd_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 rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,enqueue);
-
- rc = OBP(export->exp_obd, enqueue)(conn, md, 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 *md, __u32 mode,
- struct lustre_handle *lockh)
-{
- int rc;
- struct obd_export *export;
- OBD_CHECK_SETUP(conn, export);
- OBD_CHECK_OP(export->exp_obd,cancel);
-
- rc = OBP(export->exp_obd, cancel)(conn, md, mode, lockh);
- RETURN(rc);
-}
-
-#endif
-
-/*
- * ======== OBD Metadata Support ===========
- */
-
-extern int obd_init_caches(void);
-extern void obd_cleanup_caches(void);
-
-static inline int obdo_has_inline(struct obdo *obdo)
-{
- return (obdo->o_valid & OBD_MD_FLINLINE &&
- obdo->o_obdflags & OBD_FL_INLINEDATA);
-};
-
-#ifdef __KERNEL__
-/* support routines */
-extern kmem_cache_t *obdo_cachep;
-static inline struct obdo *obdo_alloc(void)
-{
- struct obdo *oa = NULL;
-
- 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_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)
-{
- unsigned int ia_valid = oa->o_valid;
-
- memset(attr, 0, sizeof(*attr));
- if (ia_valid & OBD_MD_FLATIME) {
- attr->ia_atime = oa->o_atime;
- attr->ia_valid |= ATTR_ATIME;
- }
- if (ia_valid & OBD_MD_FLMTIME) {
- attr->ia_mtime = oa->o_mtime;
- attr->ia_valid |= ATTR_MTIME;
- }
- if (ia_valid & OBD_MD_FLCTIME) {
- attr->ia_ctime = oa->o_ctime;
- attr->ia_valid |= ATTR_CTIME;
- }
- if (ia_valid & OBD_MD_FLSIZE) {
- attr->ia_size = oa->o_size;
- attr->ia_valid |= ATTR_SIZE;
- }
- if (ia_valid & OBD_MD_FLMODE) {
- attr->ia_mode = oa->o_mode;
- attr->ia_valid |= ATTR_MODE;
- if (!in_group_p(oa->o_gid) && !capable(CAP_FSETID))
- attr->ia_mode &= ~S_ISGID;
- }
- if (ia_valid & OBD_MD_FLUID)
- {
- attr->ia_uid = oa->o_uid;
- attr->ia_valid |= ATTR_UID;
- }
- if (ia_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). */
-
-static inline void obdo_from_inode(struct obdo *dst, struct inode *src)
-{
- if ( dst->o_valid & OBD_MD_FLID )
- dst->o_id = src->i_ino;
- if ( dst->o_valid & OBD_MD_FLATIME )
- dst->o_atime = src->i_atime;
- if ( dst->o_valid & OBD_MD_FLMTIME )
- dst->o_mtime = src->i_mtime;
- if ( dst->o_valid & OBD_MD_FLCTIME )
- dst->o_ctime = src->i_ctime;
- if ( dst->o_valid & OBD_MD_FLSIZE )
- dst->o_size = src->i_size;
- if ( dst->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */
- dst->o_blocks = src->i_blocks;
- if ( dst->o_valid & OBD_MD_FLBLKSZ )
- dst->o_blksize = src->i_blksize;
- if ( dst->o_valid & OBD_MD_FLMODE )
- dst->o_mode = src->i_mode;
- if ( dst->o_valid & OBD_MD_FLUID )
- dst->o_uid = src->i_uid;
- if ( dst->o_valid & OBD_MD_FLGID )
- dst->o_gid = src->i_gid;
- if ( dst->o_valid & OBD_MD_FLFLAGS )
- dst->o_flags = src->i_flags;
- if ( dst->o_valid & OBD_MD_FLNLINK )
- dst->o_nlink = src->i_nlink;
- if ( dst->o_valid & OBD_MD_FLGENER )
- dst->o_generation = src->i_generation;
- if ( dst->o_valid & OBD_MD_FLRDEV )
- dst->o_rdev = src->i_rdev;
-}
-
-static inline void obdo_to_inode(struct inode *dst, struct obdo *src)
-{
-
- if ( src->o_valid & OBD_MD_FLID )
- dst->i_ino = src->o_id;
- if ( src->o_valid & OBD_MD_FLATIME )
- dst->i_atime = src->o_atime;
- if ( src->o_valid & OBD_MD_FLMTIME )
- dst->i_mtime = src->o_mtime;
- if ( src->o_valid & OBD_MD_FLCTIME )
- dst->i_ctime = src->o_ctime;
- if ( src->o_valid & OBD_MD_FLSIZE )
- dst->i_size = src->o_size;
- if ( src->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */
- dst->i_blocks = src->o_blocks;
- if ( src->o_valid & OBD_MD_FLBLKSZ )
- dst->i_blksize = src->o_blksize;
- if ( src->o_valid & OBD_MD_FLMODE )
- dst->i_mode = src->o_mode;
- if ( src->o_valid & OBD_MD_FLUID )
- dst->i_uid = src->o_uid;
- if ( src->o_valid & OBD_MD_FLGID )
- dst->i_gid = src->o_gid;
- if ( src->o_valid & OBD_MD_FLFLAGS )
- dst->i_flags = src->o_flags;
- if ( src->o_valid & OBD_MD_FLNLINK )
- dst->i_nlink = src->o_nlink;
- if ( src->o_valid & OBD_MD_FLGENER )
- dst->i_generation = src->o_generation;
- if ( src->o_valid & OBD_MD_FLRDEV )
- dst->i_rdev = src->o_rdev;
-}
-
-#endif
-
-static inline void obdo_cpy_md(struct obdo *dst, struct obdo *src)
-{
-#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 ( src->o_valid & OBD_MD_FLATIME )
- dst->o_atime = src->o_atime;
- if ( src->o_valid & OBD_MD_FLMTIME )
- dst->o_mtime = src->o_mtime;
- if ( src->o_valid & OBD_MD_FLCTIME )
- dst->o_ctime = src->o_ctime;
- if ( src->o_valid & OBD_MD_FLSIZE )
- dst->o_size = src->o_size;
- if ( src->o_valid & OBD_MD_FLBLOCKS ) /* allocation of space */
- dst->o_blocks = src->o_blocks;
- if ( src->o_valid & OBD_MD_FLBLKSZ )
- dst->o_blksize = src->o_blksize;
- if ( src->o_valid & OBD_MD_FLMODE )
- dst->o_mode = src->o_mode;
- if ( src->o_valid & OBD_MD_FLUID )
- dst->o_uid = src->o_uid;
- if ( src->o_valid & OBD_MD_FLGID )
- dst->o_gid = src->o_gid;
- if ( src->o_valid & OBD_MD_FLFLAGS )
- dst->o_flags = src->o_flags;
- /*
- if ( src->o_valid & OBD_MD_FLOBDFLG )
- dst->o_obdflags = src->o_obdflags;
- */
- if ( src->o_valid & OBD_MD_FLNLINK )
- dst->o_nlink = src->o_nlink;
- if ( src->o_valid & OBD_MD_FLGENER )
- dst->o_generation = src->o_generation;
- if ( src->o_valid & OBD_MD_FLRDEV )
- dst->o_rdev = src->o_rdev;
- if ( src->o_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 |= src->o_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_FLMODE )
- res = (res || (dst->o_mode != src->o_mode));
- 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__
-int class_register_type(struct obd_ops *ops, char *nm);
-int class_unregister_type(char *nm);
-int class_name2dev(char *name);
-int class_uuid2dev(char *name);
-struct obd_device *class_uuid2obd(char *name);
-struct obd_export *class_new_export(struct obd_device *obddev);
-int class_connect(struct lustre_handle *conn, struct obd_device *obd,
- char *cluuid);
-int class_disconnect(struct lustre_handle *conn);
-void class_disconnect_all(struct obd_device *obddev);
-struct obd_export *class_conn2export(struct lustre_handle *);
-
-/* 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);
-
-
-#endif
-
-/* sysctl.c */
-extern void obd_sysctl_init (void);
-extern void obd_sysctl_clean (void);
-
-#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
- */
-
-
-#ifndef OBD_ECHO_DEVICENAME
-#define OBD_ECHO_DEVICENAME "obdecho"
-#endif
-
-extern struct obd_ops echo_obd_ops;
-
-#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
-#ifndef _OBD_FILTER_H
-#define _OBD_FILTER_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
- */
-
-#include <linux/obd_class.h>
-
-#ifndef OBD_FILTER_DEVICENAME
-#define OBD_FILTER_DEVICENAME "obdfilter"
-#endif
-
-extern struct obd_ops filter_obd_ops;
-
-#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);
-
-
-#endif
-#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(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/autoconf.h>
-#include <linux/slab.h>
-#include <linux/kp30.h>
-
-/* global variables */
-extern unsigned long obd_memory;
-extern unsigned long obd_fail_loc;
-
-#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 OBB_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
-
-/* 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");
-
-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, bdevname(dev));
- dev_set_rdonly(dev, 2);
-#else
- CERROR("obd_fail_loc=%x, can't fail write operation on %s\n",
- id, 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 { \
- long s = (size); \
- (ptr) = kmalloc(s, GFP_KERNEL); \
- if ((ptr) == NULL) { \
- CERROR("kmalloc of '" #ptr "' (%ld bytes) failed " \
- "at %s:%d\n", s, __FILE__, __LINE__); \
- } else { \
- memset((ptr), 0, s); \
- obd_memory += s; \
- CDEBUG(D_MALLOC, "kmalloced '" #ptr "': %ld at " \
- "%p (tot %ld).\n", s, (ptr), obd_memory); \
- } \
-} while (0)
-
-#define OBD_FREE(ptr, size) \
-do { \
- int s = (size); \
- kfree((ptr)); \
- obd_memory -= s; \
- CDEBUG(D_MALLOC, "kfreed '" #ptr "': %d at %p (tot %ld).\n", \
- s, (ptr), obd_memory); \
-} while (0)
-
-#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
-/* object based disk file system
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copyright (C), 1999, Stelias Computing Inc
- *
- *
- */
-
-
-#ifndef _OBDFS_H
-#define _OBDFS_H
-#include <linux/obd_class.h>
-#include <linux/list.h>
-
-static inline struct obdo *obdo_fromid(struct lustre_handle *conn, obd_id id,
- obd_mode mode, obd_flag valid)
-{
- struct obdo *oa;
- int err;
-
- ENTRY;
- oa = obdo_alloc();
- if ( !oa ) {
- RETURN(ERR_PTR(-ENOMEM));
- }
-
- oa->o_id = id;
- oa->o_mode = mode;
- oa->o_valid = valid;
- if ((err = obd_getattr(conn, oa))) {
- obdo_free(oa);
- RETURN(ERR_PTR(err));
- }
- RETURN(oa);
-}
-
-
-struct obdfs_inode_info {
- int oi_flags;
- struct list_head oi_inodes;
- struct list_head oi_pages;
- char oi_inline[OBD_INLINESZ];
-};
-
-struct obdfs_sb_info {
- struct list_head osi_list; /* list of supers */
- struct lustre_handle osi_conn;
- struct super_block *osi_super;
- struct obd_device *osi_obd;
- ino_t osi_rootino; /* number of root inode */
- int osi_minor; /* minor of /dev/obdX */
- struct list_head osi_inodes; /* list of dirty inodes */
- unsigned long osi_cache_count;
- struct semaphore osi_list_mutex;
-};
-
-
-static inline struct obdfs_inode_info *obdfs_i2info(struct inode *inode)
-{
- return (struct obdfs_inode_info *)&(inode->u.generic_ip);
-}
-
-static inline int obdfs_has_inline(struct inode *inode)
-{
- return (obdfs_i2info(inode)->oi_flags & OBD_FL_INLINEDATA);
-}
-
-static void inline obdfs_from_inode(struct obdo *oa, struct inode *inode)
-{
- struct obdfs_inode_info *oinfo = obdfs_i2info(inode);
-
- CDEBUG(D_INFO, "src inode %ld, dst obdo %ld valid 0x%08x\n",
- inode->i_ino, (long)oa->o_id, oa->o_valid);
- obdo_from_inode(oa, inode);
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
- CDEBUG(D_INODE, "copying device %x from inode to obdo\n",
- inode->i_rdev);
- *((obd_rdev *)oa->o_inline) = kdev_t_to_nr(inode->i_rdev);
- oa->o_obdflags |= OBD_FL_INLINEDATA;
- oa->o_valid |= OBD_MD_FLINLINE;
- } else if (obdfs_has_inline(inode)) {
- CDEBUG(D_INODE, "copying inline data from inode to obdo\n");
- memcpy(oa->o_inline, oinfo->oi_inline, OBD_INLINESZ);
- oa->o_obdflags |= OBD_FL_INLINEDATA;
- oa->o_valid |= OBD_MD_FLINLINE;
- }
-} /* obdfs_from_inode */
-
-static void inline obdfs_to_inode(struct inode *inode, struct obdo *oa)
-{
- struct obdfs_inode_info *oinfo = obdfs_i2info(inode);
-
- CDEBUG(D_INFO, "src obdo %ld valid 0x%08x, dst inode %ld\n",
- (long)oa->o_id, oa->o_valid, inode->i_ino);
-
- obdo_to_inode(inode, oa);
-
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
- S_ISFIFO(inode->i_mode)) {
- obd_rdev rdev = *((obd_rdev *)oa->o_inline);
- init_special_inode(inode, inode->i_mode, rdev);
- }
- if (obdo_has_inline(oa)) {
- CDEBUG(D_INFO, "copying inline from obdo to inode\n");
- memcpy(oinfo->oi_inline, oa->o_inline, OBD_INLINESZ);
- oinfo->oi_flags |= OBD_FL_INLINEDATA;
- }
-} /* obdfs_to_inode */
-
-#define NOLOCK 0
-#define LOCKED 1
-
-#ifdef OPS
-#warning "*** WARNING redefining OPS"
-#else
-#define OPS(sb,op) ((struct obdfs_sb_info *)(& (sb)->u.generic_sbp))->osi_ops->o_ ## op
-#define IOPS(inode,op) ((struct obdfs_sb_info *)(&(inode)->i_sb->u.generic_sbp))->osi_ops->o_ ## op
-#endif
-
-#ifdef ID
-#warning "*** WARNING redefining ID"
-#else
-#define ID(sb) (&((struct obdfs_sb_info *)( &(sb)->u.generic_sbp))->osi_conn)
-#define IID(inode) (&((struct obdfs_sb_info *)( &(inode)->i_sb->u.generic_sbp))->osi_conn)
-#endif
-
-#define OBDFS_SUPER_MAGIC 0x4711
-
-/* super.c */
-struct obdfs_pgrq {
- struct list_head rq_plist; /* linked list of req's */
- unsigned long rq_jiffies;
- struct page *rq_page; /* page to be written */
-};
-
-extern struct list_head obdfs_super_list; /* list of all OBDFS superblocks */
-
-
-
-/* dir.c */
-extern struct file_operations obdfs_dir_operations;
-extern struct inode_operations obdfs_dir_inode_operations;
-
-/* file.c */
-extern struct file_operations obdfs_file_operations;
-extern struct inode_operations obdfs_file_inode_operations;
-
-/* flush.c */
-void obdfs_dequeue_pages(struct inode *inode);
-int obdfs_flushd_init(void);
-int obdfs_flushd_cleanup(void);
-int obdfs_flush_reqs(struct list_head *inode_list, unsigned long check_time);
-int obdfs_flush_dirty_pages(unsigned long check_time);
-
-/* namei.c */
-
-/* rw.c */
-int obdfs_do_writepage(struct page *, int sync);
-int obdfs_init_pgrqcache(void);
-void obdfs_cleanup_pgrqcache(void);
-inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq);
-int obdfs_readpage(struct file *file, struct page *page);
-int obdfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to);
-int obdfs_commit_write(struct file *file, struct page *page, unsigned from, unsigned to);
-int obdfs_writepage(struct page *page);
-struct page *obdfs_getpage(struct inode *inode, unsigned long offset,
- int create, int locked);
-int obdfs_write_one_page(struct file *file, struct page *page,
- unsigned long offset, unsigned long bytes,
- const char * buf);
-int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io, obd_count num_oa,
- struct obdo **obdos, obd_count *oa_bufs,
- struct page **pages, char **bufs, obd_size *counts,
- obd_off *offsets, obd_flag *flags);
-void obdfs_truncate(struct inode *inode);
-
-/* super.c */
-extern long obdfs_cache_count;
-extern long obdfs_mutex_start;
-
-/* symlink.c */
-extern struct inode_operations obdfs_fast_symlink_inode_operations;
-extern struct inode_operations obdfs_symlink_inode_operations;
-
-/* sysctl.c */
-void obdfs_sysctl_init(void);
-void obdfs_sysctl_clean(void);
-
-static inline struct obdfs_sb_info *obdfs_i2sbi(struct inode *inode)
-{
- return (struct obdfs_sb_info *) &(inode->i_sb->u.generic_sbp);
-}
-
-static inline struct list_head *obdfs_iplist(struct inode *inode)
-{
- struct obdfs_inode_info *info = obdfs_i2info(inode);
-
- return &info->oi_pages;
-}
-
-static inline struct list_head *obdfs_islist(struct inode *inode)
-{
- struct obdfs_inode_info *info = obdfs_i2info(inode);
-
- return &info->oi_inodes;
-}
-
-static inline struct list_head *obdfs_slist(struct inode *inode)
-{
- struct obdfs_sb_info *sbi = obdfs_i2sbi(inode);
-
- return &sbi->osi_inodes;
-}
-
-static void inline obdfs_set_size (struct inode *inode, obd_size size)
-{
- inode->i_size = size;
- inode->i_blocks = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
- inode->i_sb->s_blocksize_bits;
-} /* obdfs_set_size */
-
-#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
-
-l_lock.c:
- test -e l_lock.c || ln -sf $(top_srcdir)/lib/l_lock.c
-l_net.c:
- test -e l_net.c || ln -sf $(top_srcdir)/lib/l_net.c
-
-LINX=l_lock.c l_net.c
-
-ldlm_SOURCES = l_lock.c ldlm_lock.c ldlm_resource.c ldlm_test.c ldlm_lockd.c \
-ldlm_extent.c ldlm_request.c l_net.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 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, 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();
-
- 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);
-
- memcpy(&lock->l_extent, &new_ex, sizeof(new_ex));
-
- 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.
- *
- * 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/slab.h>
-#include <linux/module.h>
-#include <linux/random.h>
-#include <linux/lustre_dlm.h>
-#include <linux/lustre_mds.h>
-
-/* 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",
- [LDLM_MDSINTENT] "INT"
-};
-
-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_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;
-
-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,
- [LDLM_MDSINTENT] ldlm_plain_compat
-};
-
-ldlm_res_policy ldlm_res_policy_table[] = {
- [LDLM_PLAIN] NULL,
- [LDLM_EXTENT] ldlm_extent_policy,
- [LDLM_MDSINTENT] NULL
-};
-
-void ldlm_register_intent(int (*arg) (struct ldlm_lock * lock, void *req_cookie,
- ldlm_mode_t mode, void *data))
-{
- ldlm_res_policy_table[LDLM_MDSINTENT] = arg;
-}
-
-void ldlm_unregister_intent()
-{
- ldlm_res_policy_table[LDLM_MDSINTENT] = 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);
- 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 lustre_lock *nslock = &lock->l_resource->lr_namespace->ns_lock;
- ENTRY;
-
- l_lock(nslock);
- lock->l_refc--;
- LDLM_DEBUG(lock, "after refc--");
- if (lock->l_refc < 0)
- LBUG();
-
- ldlm_resource_put(lock->l_resource);
- if (lock->l_parent)
- LDLM_LOCK_PUT(lock->l_parent);
-
- if (lock->l_refc == 0 && (lock->l_flags & LDLM_FL_DESTROYED)) {
- lock->l_resource = NULL;
- LDLM_DEBUG(lock, "final lock_put on destroyed lock, freeing");
- if (lock->l_connection)
- ptlrpc_put_connection(lock->l_connection);
- CDEBUG(D_MALLOC, "kfreed 'lock': %d at %p (tot 1).\n",
- sizeof(*lock), lock);
- kmem_cache_free(ldlm_lock_slab, lock);
- }
- l_unlock(nslock);
- 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);
- LBUG();
- }
-
- if (!list_empty(&lock->l_res_link)) {
- ldlm_lock_dump(lock);
- LBUG();
- }
-
- if (lock->l_flags & LDLM_FL_DESTROYED) {
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- EXIT;
- return;
- }
-
- lock->l_flags = LDLM_FL_DESTROYED;
- 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);
- CDEBUG(D_MALLOC, "kmalloced 'lock': %d at "
- "%p (tot %d).\n", sizeof(*lock), lock, 1);
-
- 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 */
- lock->l_refc = 1;
- INIT_LIST_HEAD(&lock->l_children);
- INIT_LIST_HEAD(&lock->l_res_link);
- init_waitqueue_head(&lock->l_waitq);
-
- 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);
- }
- /* this is the extra refcount, to prevent the lock
- 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 type, i;
- 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);
- }
-
- type = lock->l_resource->lr_type;
- if (new_resid[0] == 0)
- LBUG();
- lock->l_resource = ldlm_resource_get(ns, NULL, new_resid, type, 1);
- if (lock->l_resource == NULL) {
- LBUG();
- RETURN(-ENOMEM);
- }
-
- /* move references over */
- for (i = 0; i < lock->l_refc; i++) {
- int rc;
- ldlm_resource_getref(lock->l_resource);
- rc = ldlm_resource_put(oldres);
- if (rc == 1 && i != lock->l_refc - 1)
- LBUG();
- }
- /* compensate for the initial get above.. */
- ldlm_resource_put(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;
-}
-
-struct ldlm_lock *ldlm_handle2lock(struct lustre_handle *handle)
-{
- struct ldlm_lock *lock = NULL, *retval = NULL;
- ENTRY;
-
- if (!handle || !handle->addr)
- RETURN(NULL);
-
- lock = (struct ldlm_lock *)(unsigned long)(handle->addr);
- if (!kmem_cache_validate(ldlm_lock_slab, (void *)lock))
- RETURN(NULL);
-
- l_lock(&lock->l_resource->lr_namespace->ns_lock);
- if (lock->l_random != handle->cookie)
- GOTO(out, NULL);
-
- if (lock->l_flags & LDLM_FL_DESTROYED)
- GOTO(out, NULL);
-
- retval = LDLM_LOCK_GET(lock);
- EXIT;
- out:
- l_unlock(&lock->l_resource->lr_namespace->ns_lock);
- 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);
- 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 */
-void ldlm_lock_decref(struct lustre_handle *lockh, __u32 mode)
-{
- struct ldlm_lock *lock = ldlm_handle2lock(lockh);
- ENTRY;
-
- if (lock == NULL)
- LBUG();
-
- LDLM_DEBUG(lock, "ldlm_lock_decref(%s)", ldlm_lockname[mode]);
- 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) {
- CERROR("LDLM_FL_CBPENDING set on non-local lock!\n");
- LBUG();
- }
-
- 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);
- } 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, "incompatible; sending blocking "
- "AST.\n");
- 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 *lock;
- struct list_head *tmp;
-
- list_for_each(tmp, queue) {
- lock = list_entry(tmp, struct ldlm_lock, l_res_link);
-
- if (lock->l_flags & LDLM_FL_CBPENDING)
- continue;
-
- /* lock_convert() takes the resource lock, so we're sure that
- * req_mode, lr_type, and l_cookie won't change beneath us */
- 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;
-
- ldlm_lock_addref_internal(lock, mode);
- return lock;
- }
-
- return NULL;
-}
-
-/* Must be called with no resource or lock locks held.
- *
- * 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;
- int rc = 0;
- ENTRY;
-
- res = ldlm_resource_get(ns, NULL, res_id, type, 0);
- if (res == NULL)
- RETURN(0);
-
- ns = res->lr_namespace;
- l_lock(&ns->ns_lock);
-
- if ((lock = search_queue(&res->lr_granted, mode, cookie)))
- GOTO(out, rc = 1);
- if ((lock = search_queue(&res->lr_converting, mode, cookie)))
- GOTO(out, rc = 1);
- if ((lock = search_queue(&res->lr_waiting, mode, cookie)))
- GOTO(out, rc = 1);
-
- EXIT;
- out:
- ldlm_resource_put(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");
- 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;
-
- 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_put(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 */
- local = res->lr_namespace->ns_client;
- if (!local && (policy = ldlm_res_policy_table[res->lr_type])) {
- int rc;
- rc = policy(lock, cookie, lock->l_req_mode, 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);
- }
- }
-
- lock->l_cookie = cookie;
- lock->l_cookie_len = cookie_len;
-
- 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. */
- 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' */
- ldlm_resource_unlink_lock(lock);
- if (local) {
- 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:
- /* 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);
- 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_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)
- CDEBUG(D_INFO, "lock still has references (%d readers, %d "
- "writers)\n", lock->l_readers, lock->l_writers);
-
- ldlm_resource_unlink_lock(lock);
- ldlm_lock_destroy(lock);
- l_unlock(&ns->ns_lock);
- EXIT;
-}
-
-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 {
- 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
- list_add_tail(&lock->l_res_link, &res->lr_converting);
-
- 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_connection)
- CDEBUG(D_OTHER, " Node: NID %x (rhandle: %Lx)\n",
- lock->l_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 (%Ld)\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.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * by Cluster File Systems, Inc.
- */
-
-#define EXPORT_SYMTAB
-#define DEBUG_SUBSYSTEM S_LDLM
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/lustre_dlm.h>
-
-extern kmem_cache_t *ldlm_resource_slab;
-extern kmem_cache_t *ldlm_lock_slab;
-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);
-
-static int ldlm_server_blocking_ast(struct ldlm_lock *lock,
- struct ldlm_lock_desc *desc,
- void *data, __u32 data_len)
-{
- struct ldlm_request *body;
- struct ptlrpc_request *req;
- struct ptlrpc_client *cl;
- int rc = 0, size = sizeof(*body);
- ENTRY;
-
- cl = &lock->l_resource->lr_namespace->ns_rpc_client;
- req = ptlrpc_prep_req(cl, lock->l_connection, 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 = lustre_msg_size(0, NULL);
-
- rc = ptlrpc_queue_wait(req);
- rc = ptlrpc_check_status(req, rc);
- ptlrpc_free_req(req);
-
- RETURN(rc);
-}
-
-static int ldlm_server_completion_ast(struct ldlm_lock *lock, int flags)
-{
- struct ldlm_request *body;
- struct ptlrpc_request *req;
- struct ptlrpc_client *cl;
- int rc = 0, size = sizeof(*body);
- ENTRY;
-
- if (lock == NULL) {
- LBUG();
- RETURN(-EINVAL);
- }
-
- cl = &lock->l_resource->lr_namespace->ns_rpc_client;
- req = ptlrpc_prep_req(cl, lock->l_connection, 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 = lustre_msg_size(0, NULL);
-
- rc = ptlrpc_queue_wait(req);
- rc = ptlrpc_check_status(req, rc);
- ptlrpc_free_req(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);
- if (dlm_req->lock_desc.l_resource.lr_type == LDLM_MDSINTENT) {
- /* 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);
- }
- }
-
- 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");
-
- flags = dlm_req->lock_flags;
- 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_connection = ptlrpc_connection_addref(req->rq_connection);
- EXIT;
- out:
- if (lock)
- LDLM_DEBUG(lock, "server-side enqueue handler, sending reply"
- "(err=%d)", err);
- req->rq_status = err;
-
- if (ptlrpc_reply(req->rq_svc, req))
- LBUG();
-
- 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);
- 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 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);
-
- 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);
- 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 rc, do_ast;
- ENTRY;
-
- rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(-ENOMEM);
- rc = ptlrpc_reply(req->rq_svc, req);
- if (rc)
- RETURN(rc);
-
- dlm_req = lustre_msg_buf(req->rq_reqmsg, 0);
-
- lock = ldlm_handle2lock(&dlm_req->lock_handle1);
- if (!lock) {
- CERROR("blocking callback on lock %Lx - 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);
- }
- } 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;
- int rc;
- ENTRY;
-
- rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(-ENOMEM);
- rc = ptlrpc_reply(req->rq_svc, req);
- if (rc)
- RETURN(rc);
-
- dlm_req = lustre_msg_buf(req->rq_reqmsg, 0);
-
- lock = ldlm_handle2lock(&dlm_req->lock_handle1);
- if (!lock) {
- CERROR("completion callback on lock %Lx - 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);
- lock->l_req_mode = dlm_req->lock_desc.l_granted_mode;
-
- /* If we receive the completion AST before the actual enqueue returned,
- * then we might need to switch resources. */
- 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\n");
- GOTO(out, rc);
- }
-
- if (req->rq_reqmsg->type != PTL_RPC_MSG_REQUEST) {
- CERROR("lustre_ldlm: wrong packet type sent %d\n",
- req->rq_reqmsg->type);
- GOTO(out, rc = -EINVAL);
- }
- 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);
- break;
- 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);
- break;
-
- default:
- rc = ptlrpc_error(req->rq_svc, req);
- RETURN(rc);
- }
-
- EXIT;
-out:
- if (rc)
- RETURN(ptlrpc_error(req->rq_svc, req));
- 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));
- ptlrpc_init_client(NULL, NULL,
- LDLM_REQUEST_PORTAL, LDLM_REPLY_PORTAL,
- 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;
-}
-
-#define LDLM_NUM_THREADS 8
-
-static int ldlm_setup(struct obd_device *obddev, obd_count len, void *buf)
-{
- struct ldlm_obd *ldlm = &obddev->u.ldlm;
- int rc, i;
- ENTRY;
-
- MOD_INC_USE_COUNT;
- rc = ldlm_proc_setup(obddev);
- if (rc != 0)
- GOTO(out_dec, rc);
-
- ldlm->ldlm_service = ptlrpc_init_svc(64 * 1024, LDLM_REQUEST_PORTAL,
- LDLM_REPLY_PORTAL, "self",
- ldlm_callback_handler);
- if (!ldlm->ldlm_service)
- GOTO(out_proc, rc = -ENOMEM);
-
- for (i = 0; i < LDLM_NUM_THREADS; i++) {
- char name[32];
- sprintf(name, "lustre_dlm_%02d", i);
- rc = ptlrpc_start_thread(obddev, ldlm->ldlm_service, name);
- if (rc) {
- CERROR("cannot start LDLM thread #%d: rc %d\n", i, rc);
- LBUG();
- GOTO(out_thread, rc);
- }
- }
-
- RETURN(0);
-
- out_thread:
- ptlrpc_stop_all_threads(ldlm->ldlm_service);
- ptlrpc_unregister_service(ldlm->ldlm_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_service);
- ptlrpc_unregister_service(ldlm->ldlm_service);
- ldlm_proc_cleanup(obddev);
-
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-struct obd_ops ldlm_obd_ops = {
- o_iocontrol: ldlm_iocontrol,
- o_setup: ldlm_setup,
- o_cleanup: ldlm_cleanup,
- o_connect: class_connect,
- o_disconnect: class_disconnect
-};
-
-static int __init ldlm_init(void)
-{
- int rc = class_register_type(&ldlm_obd_ops, 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;
- }
-
- 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_match);
-EXPORT_SYMBOL(ldlm_lock_addref);
-EXPORT_SYMBOL(ldlm_lock_decref);
-EXPORT_SYMBOL(ldlm_lock_change_resource);
-EXPORT_SYMBOL(ldlm_cli_convert);
-EXPORT_SYMBOL(ldlm_cli_enqueue);
-EXPORT_SYMBOL(ldlm_cli_cancel);
-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_free);
-
-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 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>
-
-int ldlm_completion_ast(struct ldlm_lock *lock, int flags)
-{
- ENTRY;
-
- if (flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
- LDLM_FL_BLOCK_CONV)) {
- /* Go to sleep until the lock is granted. */
- /* FIXME: or cancelled. */
- LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock,"
- " sleeping");
- ldlm_lock_dump(lock);
- ldlm_reprocess_all(lock->l_resource);
- wait_event(lock->l_waitq, (lock->l_req_mode ==
- lock->l_granted_mode));
- LDLM_DEBUG(lock, "client-side enqueue waking up: granted");
- } else if (flags == LDLM_FL_WAIT_NOREPROC) {
- wait_event(lock->l_waitq, (lock->l_req_mode ==
- lock->l_granted_mode));
- } else if (flags == 0) {
- wake_up(&lock->l_waitq);
- }
-
- 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;
-
- if (ns->ns_client) {
- CERROR("Trying to cancel local lock\n");
- LBUG();
- }
-
- lock = ldlm_lock_create(ns, parent_lockh, res_id, type, mode, NULL, 0);
- 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 ptlrpc_connection *connection;
- struct ldlm_lock *lock;
- struct ldlm_request *body;
- struct ldlm_reply *reply;
- int rc, size = sizeof(*body), req_passed_in = 1;
- ENTRY;
-
- 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);
- connection = client_conn2cli(connh)->cl_conn;
-
- *flags = 0;
- 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 (req == NULL) {
- req = ptlrpc_prep_req2(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 all of this data into the request buffer */
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- ldlm_lock2desc(lock, &body->lock_desc);
- /* Phil: make this part of ldlm_lock2desc */
- if (type == LDLM_EXTENT)
- memcpy(&body->lock_desc.l_extent, cookie,
- sizeof(body->lock_desc.l_extent));
- 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_connection = ptlrpc_connection_addref(connection);
- lock->l_client = client_conn2cli(connh)->cl_client;
-
- rc = ptlrpc_queue_wait(req);
- /* FIXME: status check here? */
- rc = ptlrpc_check_status(req, rc);
-
- if (rc != ELDLM_OK) {
- 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));
- if (type == LDLM_EXTENT)
- memcpy(cookie, &reply->lock_extent, sizeof(reply->lock_extent));
- *flags = reply->lock_flags;
-
- CDEBUG(D_INFO, "remote handle: %p, flags: %d\n",
- (void *)(unsigned long)reply->lock_handle.addr, *flags);
- CDEBUG(D_INFO, "extent: %Lu -> %Lu\n",
- (unsigned long long)reply->lock_extent.start,
- (unsigned long long)reply->lock_extent.end);
-
- /* 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;
- 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 (!req_passed_in)
- ptlrpc_free_req(req);
-
- rc = ldlm_lock_enqueue(lock, cookie, cookielen, flags, completion,
- blocking);
- if (lock->l_completion_ast)
- lock->l_completion_ast(lock, *flags);
-
- 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);
-}
-
-static int ldlm_cli_convert_local(struct ldlm_lock *lock, int new_mode,
- int *flags)
-{
-
- 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);
-}
-
-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_req2(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);
- rc = ptlrpc_check_status(req, rc);
- 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_free_req(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;
-
- lock = ldlm_handle2lock(lockh);
- if (!lock) {
- /* It's possible that the decref that we did just before this
- * cancel was the last reader/writer, and caused a cancel before
- * we could call this function. If we want to make this
- * impossible (by adding a dec_and_cancel() or similar), then
- * we can put the LBUG back. */
- //LBUG();
- RETURN(-EINVAL);
- }
-
- if (lock->l_connh) {
- LDLM_DEBUG(lock, "client-side cancel");
- req = ptlrpc_prep_req2(lock->l_connh, LDLM_CANCEL, 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));
-
- req->rq_replen = lustre_msg_size(0, NULL);
-
- rc = ptlrpc_queue_wait(req);
- rc = ptlrpc_check_status(req, rc);
- ptlrpc_free_req(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");
- }
-
- EXIT;
- out:
- LDLM_LOCK_PUT(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>
-
-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;
-
- if (obd->obd_proc_entry == NULL)
- RETURN(-EINVAL);
-
- ldlm_ns_proc_dir = proc_mkdir("namespaces", obd->obd_proc_entry);
- if (ldlm_ns_proc_dir == NULL) {
- CERROR("Couldn't create /proc/lustre/ldlm/namespaces\n");
- RETURN(-EPERM);
- }
- RETURN(0);
-}
-
-void ldlm_proc_cleanup(struct obd_device *obd)
-{
- proc_lustre_remove_obd_entry("namespaces", obd);
-}
-
-struct ldlm_namespace *ldlm_namespace_new(char *name, __u32 client)
-{
- struct ldlm_namespace *ns = NULL;
- struct list_head *bucket;
-
- 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);
-
- ptlrpc_init_client(NULL, NULL, LDLM_REQUEST_PORTAL, LDLM_REPLY_PORTAL,
- &ns->ns_rpc_client);
-
- INIT_LIST_HEAD(&ns->ns_root_list);
- l_lock_init(&ns->ns_lock);
- ns->ns_refcount = 0;
- ns->ns_client = client;
-
- for (bucket = ns->ns_hash + RES_HASH_SIZE - 1; bucket >= ns->ns_hash;
- bucket--)
- INIT_LIST_HEAD(bucket);
-
- spin_lock(&ldlm_namespace_lock);
- list_add(&ns->ns_list_chain, &ldlm_namespace_list);
- ns->ns_proc_dir = proc_mkdir(ns->ns_name, ldlm_ns_proc_dir);
- if (ns->ns_proc_dir == NULL)
- CERROR("Unable to create proc directory for namespace.\n");
- spin_unlock(&ldlm_namespace_lock);
-
- RETURN(ns);
-
- out:
- if (ns && ns->ns_hash) {
- 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);
-
-static void cleanup_resource(struct ldlm_resource *res, struct list_head *q)
-{
- 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);
-
- if (client) {
- struct lustre_handle lockh;
- ldlm_lock2handle(lock, &lockh);
- /* can we get away without a connh here? */
- rc = ldlm_cli_cancel(&lockh);
- if (rc != ELDLM_OK) {
- /* It failed remotely, but we'll force it to
- * cleanup locally. */
- CERROR("ldlm_cli_cancel: %d\n", rc);
- 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_free(struct ldlm_namespace *ns)
-{
- struct list_head *tmp, *pos;
- int i;
-
- if (!ns)
- RETURN(ELDLM_OK);
-
- spin_lock(&ldlm_namespace_lock);
- list_del(&ns->ns_list_chain);
- remove_proc_entry(ns->ns_name, ldlm_ns_proc_dir);
- spin_unlock(&ldlm_namespace_lock);
-
- l_lock(&ns->ns_lock);
-
- for (i = 0; i < RES_HASH_SIZE; i++) {
- 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);
- cleanup_resource(res, &res->lr_converting);
- cleanup_resource(res, &res->lr_waiting);
-
- if (!ldlm_resource_put(res)) {
- 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_put(res);
- }
- }
- }
-
- vfree(ns->ns_hash /* , sizeof(*ns->ns_hash) * RES_HASH_SIZE */);
- obd_memory -= sizeof(*ns->ns_hash) * RES_HASH_SIZE;
- ptlrpc_cleanup_client(&ns->ns_rpc_client);
- OBD_FREE(ns->ns_name, strlen(ns->ns_name) + 1);
- OBD_FREE(ns, sizeof(*ns));
-
- return ELDLM_OK;
-}
-
-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);
- }
-
- 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);
- }
-
- 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);
- EXIT;
- break;
- }
- }
-
- if (res == NULL && 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);
- return res;
-}
-
-/* Returns 1 if the resource was freed, 0 if it remains. */
-int ldlm_resource_put(struct ldlm_resource *res)
-{
- int rc = 0;
-
- if (atomic_dec_and_test(&res->lr_refcount)) {
- struct ldlm_namespace *ns = res->lr_namespace;
- ENTRY;
-
- l_lock(&ns->ns_lock);
-
- if (atomic_read(&res->lr_refcount) != 0) {
- /* We lost the race. */
- l_unlock(&ns->ns_lock);
- goto out;
- }
-
- if (!list_empty(&res->lr_granted))
- LBUG();
-
- if (!list_empty(&res->lr_converting))
- LBUG();
-
- if (!list_empty(&res->lr_waiting))
- LBUG();
-
- if (!list_empty(&res->lr_children))
- LBUG();
-
- ns->ns_refcount--;
- list_del(&res->lr_hash);
- list_del(&res->lr_childof);
-
- kmem_cache_free(ldlm_resource_slab, res);
- l_unlock(&ns->ns_lock);
- rc = 1;
- } else {
- ENTRY;
- out:
- if (atomic_read(&res->lr_refcount) < 0)
- LBUG();
- }
-
- 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);
-
- if (!list_empty(&lock->l_res_link))
- LBUG();
-
- 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>
-
-struct ldlm_test_thread {
- struct lustre_handle *connh;
- 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;
- ldlm_mode_t l_mode;
-};
-
-static const int max_locks = 10;
-
-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 locks_granted = ATOMIC_INIT(0);
-static atomic_t locks_matched = ATOMIC_INIT(0);
-
-/*
- * 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 rc;
- struct lustre_handle lockh;
- ENTRY;
-
- LDLM_DEBUG_NOLOCK("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();
- }
-
- 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)
-{
- ENTRY;
- CERROR("ldlm_blocking_ast: lock=%p, new=%p\n", lock, new);
- RETURN(0);
-}
-
-/* Completion ast for regression test.
- * Does not sleep when blocked.
- */
-static int ldlm_test_completion_ast(struct ldlm_lock *lock, int flags)
-{
-
- ENTRY;
-
- if (flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
- LDLM_FL_BLOCK_CONV)) {
- /* Do nothing */
- LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock");
- ldlm_lock_dump(lock);
- } else {
- /* add to list of granted locks */
- struct ldlm_test_lock *lock_info;
-
- if (flags == LDLM_FL_WAIT_NOREPROC) {
- atomic_inc(&locks_matched);
- LDLM_DEBUG(lock, "lock matched");
- } else if (flags == LDLM_FL_LOCK_CHANGED) {
- atomic_inc(&locks_granted);
- LDLM_DEBUG(lock, "lock changed and granted");
- } 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);
- lock_info->l_mode = lock->l_granted_mode;
-
- spin_lock(&ctl_lock);
- list_add_tail(&lock_info->l_link, &lock_list);
- num_locks++;
-
- /* if we're over the max of granted locks, decref some */
- if (num_locks > max_locks) {
- /* 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
- * Don't hold ctl_lock here. The decref
- * may result in another lock being granted
- * and hence this function being called again.
- */
- LDLM_DEBUG_NOLOCK("Decrementing lock");
- ldlm_lock_decref(&lock_info->l_lockh,
- lock_info->l_mode);
- OBD_FREE(lock_info, sizeof(*lock_info));
-
- spin_lock(&ctl_lock);
- }
- 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;
-
- 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;
-
- 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;
- int flags = 0;
- ldlm_error_t err;
-
- 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);
-
- if (err == ELDLM_OK)
- ldlm_lock_decref(&lockh1, LCK_EX);
-
- RETURN(err);
-}
-
-static int ldlm_test_main(void *data)
-{
- struct ldlm_test_thread *thread = data;
- const unsigned int num_resources = 10;
- const unsigned int num_extent = 10;
- ENTRY;
-
- lock_kernel();
- daemonize();
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
-
- sprintf(current->comm, "ldlm_test");
-
- /* Record that the thread is running */
- thread->t_flags |= SVC_RUNNING;
- wake_up(&thread->t_ctl_waitq);
-
- while (!(thread->t_flags & SVC_STOPPING)) {
- struct lustre_handle lockh;
- __u64 res_id[3] = {0};
- __u32 lock_mode;
- struct ldlm_extent ext;
- char random;
- int flags = 0, rc = 0;
-
- /* Pick a random resource from 1 to num_resources */
- get_random_bytes(&random, sizeof(random));
- res_id[0] = (unsigned char)random % num_resources;
-
- /* Pick a random lock mode */
- get_random_bytes(&random, sizeof(random));
- lock_mode = (unsigned char)random % LCK_NL + 1;
-
- /* Pick a random extent */
- get_random_bytes(&random, sizeof(random));
- ext.start = (unsigned int)random % num_extent;
- get_random_bytes(&random, sizeof(random));
- ext.end = (unsigned int)random %
- (num_extent - (int)ext.start) + ext.start;
-
- LDLM_DEBUG_NOLOCK("about to enqueue with resource %d, mode %d,"
- " extent %d -> %d", (int)res_id[0], lock_mode,
- (int)ext.start, (int)ext.end);
-
- rc = ldlm_match_or_enqueue(thread->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();
- }
-
- LDLM_DEBUG_NOLOCK("locks requested: %d, granted: %d, "
- "matched: %d",
- atomic_read(&locks_requested),
- atomic_read(&locks_granted),
- atomic_read(&locks_matched));
-
- /* I think this may be necessary since we don't sleep
- * after a lock being blocked
- */
- 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->connh = connh;
- 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, int count)
-{
- 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);
-
- for (i = 0; i < count; i++) {
- rc = ldlm_start_thread(obddev, connh);
- if (rc < 0)
- GOTO(cleanup, rc);
- }
-
- cleanup:
- 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));
- }
-
- 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 page.c ll_pack.c l_lock.c simple.c l_net.c\
- lov_pack.c
-
-include $(top_srcdir)/Rules
+++ /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
-
-#include <linux/obd_ost.h>
-#include <linux/lustre_debug.h>
-
-int dump_ioo(struct obd_ioobj *ioo)
-{
- CERROR("obd_ioobj: ioo_id=%Ld, ioo_gr=%Ld, 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=%Ld, 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=%Ld, len=%d, flags=%x, xid=%d\n",
- nb->offset, nb->len, nb->flags, nb->xid);
-
- return -EINVAL;
-}
-
-int dump_obdo(struct obdo *oa)
-{
- CERROR("obdo: o_valid = %08x\n", oa->o_valid);
- if (oa->o_valid & OBD_MD_FLID)
- CERROR("obdo: o_id = %Ld\n", oa->o_id);
- if (oa->o_valid & OBD_MD_FLATIME)
- CERROR("obdo: o_atime = %Ld\n", oa->o_atime);
- if (oa->o_valid & OBD_MD_FLMTIME)
- CERROR("obdo: o_mtime = %Ld\n", oa->o_mtime);
- if (oa->o_valid & OBD_MD_FLCTIME)
- CERROR("obdo: o_ctime = %Ld\n", oa->o_ctime);
- if (oa->o_valid & OBD_MD_FLSIZE)
- CERROR("obdo: o_size = %Ld\n", oa->o_size);
- if (oa->o_valid & OBD_MD_FLBLOCKS) /* allocation of space */
- CERROR("obdo: o_blocks = %Ld\n", oa->o_blocks);
- if (oa->o_valid & OBD_MD_FLBLKSZ)
- CERROR("obdo: o_blksize = %d\n", oa->o_blksize);
- if (oa->o_valid & OBD_MD_FLMODE)
- CERROR("obdo: o_mode = %o\n", oa->o_mode);
- if (oa->o_valid & OBD_MD_FLUID)
- CERROR("obdo: o_uid = %d\n", oa->o_uid);
- if (oa->o_valid & OBD_MD_FLGID)
- CERROR("obdo: o_gid = %d\n", oa->o_gid);
- if (oa->o_valid & OBD_MD_FLFLAGS)
- CERROR("obdo: o_flags = %x\n", oa->o_flags);
- if (oa->o_valid & OBD_MD_FLNLINK)
- CERROR("obdo: o_nlink = %d\n", oa->o_nlink);
- if (oa->o_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);
-
- CERROR("ost_body: connid = %d, data = %d\n", body->connid, body->data);
- dump_obdo(&body->oa);
- //dump_niobuf(nb);
- dump_ioo(ioo);
-
- return -EINVAL;
-}
-
+++ /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/locks.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)
-{
- if (lock->l_owner != current)
- LBUG();
- if (lock->l_depth < 0)
- LBUG();
-
- 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);
-}
+++ /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>
-
-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;
-}
-extern struct recovd_obd *ptlrpc_connmgr;
-
-int client_obd_setup(struct obd_device *obddev, obd_count len, void *buf)
-{
- struct obd_ioctl_data* data = buf;
- int rq_portal = (obddev->obd_type->typ_ops->o_getattr) ? OST_REQUEST_PORTAL : MDS_REQUEST_PORTAL;
- int rp_portal = (obddev->obd_type->typ_ops->o_getattr) ? OSC_REPLY_PORTAL : MDC_REPLY_PORTAL;
- struct client_obd *mdc = &obddev->u.cli;
- char server_uuid[37];
- int rc;
- ENTRY;
-
- 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(&mdc->cl_sem, 1);
- mdc->cl_conn_count = 0;
- memcpy(mdc->cl_target_uuid, data->ioc_inlbuf1, data->ioc_inllen1);
- memcpy(server_uuid, data->ioc_inlbuf2, MIN(data->ioc_inllen2,
- sizeof(server_uuid)));
-
- mdc->cl_conn = ptlrpc_uuid_to_connection(server_uuid);
- if (!mdc->cl_conn)
- RETURN(-ENOENT);
-
- OBD_ALLOC(mdc->cl_client, sizeof(*mdc->cl_client));
- if (mdc->cl_client == NULL)
- GOTO(out_conn, rc = -ENOMEM);
-
- OBD_ALLOC(mdc->cl_ldlm_client, sizeof(*mdc->cl_ldlm_client));
- if (mdc->cl_ldlm_client == NULL)
- GOTO(out_client, rc = -ENOMEM);
-
- /* XXX get recovery hooked in here again */
- //ptlrpc_init_client(ptlrpc_connmgr, ll_recover,...
-
- ptlrpc_init_client(NULL, NULL, rq_portal, rp_portal, mdc->cl_client);
- ptlrpc_init_client(NULL, NULL, LDLM_REQUEST_PORTAL, LDLM_REPLY_PORTAL,
- mdc->cl_ldlm_client);
- mdc->cl_client->cli_name = "mdc";
- mdc->cl_ldlm_client->cli_name = "ldlm";
- mdc->cl_max_mdsize = sizeof(struct lov_stripe_md);
-
- MOD_INC_USE_COUNT;
- RETURN(0);
-
- out_client:
- OBD_FREE(mdc->cl_client, sizeof(*mdc->cl_client));
- out_conn:
- ptlrpc_put_connection(mdc->cl_conn);
- return rc;
-}
-
-int client_obd_cleanup(struct obd_device * obddev)
-{
- struct client_obd *mdc = &obddev->u.cli;
-
- ptlrpc_cleanup_client(mdc->cl_client);
- OBD_FREE(mdc->cl_client, sizeof(*mdc->cl_client));
- ptlrpc_cleanup_client(mdc->cl_ldlm_client);
- OBD_FREE(mdc->cl_ldlm_client, sizeof(*mdc->cl_ldlm_client));
- ptlrpc_put_connection(mdc->cl_conn);
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-int client_obd_connect(struct lustre_handle *conn, struct obd_device *obd,
- char *cluuid)
-{
- 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_getattr) ? OST_CONNECT : MDS_CONNECT;
-
- ENTRY;
- down(&cli->cl_sem);
- MOD_INC_USE_COUNT;
-#warning shaver: we might need a real cluuid here
- rc = class_connect(conn, obd, NULL);
- if (rc) {
- MOD_DEC_USE_COUNT;
- GOTO(out_sem, rc);
- }
-
- cli->cl_conn_count++;
- if (cli->cl_conn_count > 1)
- GOTO(out_sem, rc);
-
- obd->obd_namespace = ldlm_namespace_new(obd->obd_name,
- LDLM_NAMESPACE_CLIENT);
- if (obd->obd_namespace == NULL)
- GOTO(out_disco, rc = -ENOMEM);
-
- request = ptlrpc_prep_req(cli->cl_client, cli->cl_conn, 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);
- // This handle may be important if a callback needs
- // to find the mdc/osc
- // request->rq_reqmsg->addr = conn->addr;
- // request->rq_reqmsg->cookie = conn->cookie;
-
- rc = ptlrpc_queue_wait(request);
- rc = ptlrpc_check_status(request, rc);
- if (rc)
- GOTO(out_req, rc);
-
- request->rq_connection->c_level = LUSTRE_CONN_FULL;
- cli->cl_exporth = *(struct lustre_handle *)request->rq_repmsg;
-
- EXIT;
-out_req:
- ptlrpc_free_req(request);
- if (rc) {
-out_ldlm:
- ldlm_namespace_free(obd->obd_namespace);
- obd->obd_namespace = NULL;
-out_disco:
- 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 = (obd->obd_type->typ_ops->o_getattr) ? OST_DISCONNECT : MDS_DISCONNECT;
- struct ptlrpc_request *request = NULL;
- int rc, err;
- ENTRY;
-
- 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_req2(conn, rq_opc, 0, NULL, NULL);
- if (!request)
- GOTO(out_disco, rc = -ENOMEM);
-
- request->rq_replen = lustre_msg_size(0, NULL);
-
- rc = ptlrpc_queue_wait(request);
- if (rc)
- GOTO(out_req, rc);
-
- EXIT;
- out_req:
- if (request)
- ptlrpc_free_req(request);
- out_disco:
- err = class_disconnect(conn);
- if (!rc && err)
- rc = err;
- MOD_DEC_USE_COUNT;
- out_sem:
- up(&cli->cl_sem);
- RETURN(rc);
-}
-
-int target_handle_connect(struct ptlrpc_request *req)
-{
- struct obd_device *target;
- struct obd_export *export;
- 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 = lustre_pack_msg(0,
- NULL, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- GOTO(out, rc);
-
- rc = obd_connect(&conn, target, cluuid);
- 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 = req->rq_connection;
-#warning Peter: is this the right place to upgrade the server connection level?
- req->rq_connection->c_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);
-}
+++ /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 *osfs, struct statfs *sfs)
-{
- if (osfs == NULL || sfs == NULL)
- LBUG();
-
- osfs->os_type = HTON__u64(sfs->f_type);
- osfs->os_blocks = HTON__u64(sfs->f_blocks);
- osfs->os_bfree = HTON__u64(sfs->f_bfree);
- osfs->os_bavail = HTON__u64(sfs->f_bavail);
- osfs->os_files = HTON__u64(sfs->f_files);
- osfs->os_ffree = HTON__u64(sfs->f_ffree);
- osfs->os_bsize = HTON__u32(sfs->f_bsize);
- osfs->os_namelen = HTON__u32(sfs->f_namelen);
-}
-
-void obd_statfs_unpack(struct obd_statfs *osfs, struct statfs *sfs)
-{
- if (osfs == NULL || sfs == NULL)
- LBUG();
-
- sfs->f_type = NTOH__u64(osfs->os_type);
- sfs->f_blocks = NTOH__u64(osfs->os_blocks);
- sfs->f_bfree = NTOH__u64(osfs->os_bfree);
- sfs->f_bavail = NTOH__u64(osfs->os_bavail);
- sfs->f_files = NTOH__u64(osfs->os_files);
- sfs->f_ffree = NTOH__u64(osfs->os_ffree);
- sfs->f_bsize = NTOH__u32(osfs->os_bsize);
- sfs->f_namelen = NTOH__u32(osfs->os_namelen);
-}
-
+++ /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 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);
-}
-
-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);
-}
+++ /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>
-#include <linux/locks.h>
-#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_FLMODE | OBD_MD_FLSIZE | OBD_MD_FLUID |
- OBD_MD_FLGID | 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->major = HTON__u32(inode->i_major);
- //b->minor = HTON__u32(inode->i_minor);
- 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();
-
- mds_pack_fid(&b->fid1);
- mds_pack_fid(&b->fid2);
- b->extra = HTON__u64(b->extra);
- b->size = HTON__u64(b->size);
- 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->major = HTON__u32(b->major);
- b->minor = HTON__u32(b->minor);
- b->ino = HTON__u32(b->ino);
- 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 *rec;
- rec = lustre_msg_buf(req->rq_reqmsg, offset);
-
- ll_inode2fid(&rec->fid1, inode);
- if (name) {
- char *tmp;
- tmp = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- LOGL0(name, namelen, tmp);
- }
-}
-
-
-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 *inode, __u32 mode, __u64 rdev, __u32 uid,
- __u32 gid, __u64 time, const char *name, int namelen,
- const char *tgt, int tgtlen)
-{
- 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);
- ll_inode2fid(&rec->cr_fid, inode);
- 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 (tgt) {
- tmp = lustre_msg_buf(req->rq_reqmsg, offset + 2);
- LOGL0(tgt, tgtlen, 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);
- 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_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);
- 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);
- 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->extra = NTOH__u64(b->extra);
- b->size = NTOH__u64(b->size);
- b->valid = NTOH__u32(b->valid);
- 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->major = NTOH__u32(b->major);
- b->minor = NTOH__u32(b->minor);
- b->ino = NTOH__u32(b->ino);
- 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_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 + 3 ||
- req->rq_reqmsg->buflens[offset] != sizeof(*rec))
- RETURN(-EFAULT);
-
- r->ur_fid1 = &rec->cr_fid;
- 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];
-
- r->ur_tgt = lustre_msg_buf(req->rq_reqmsg, offset + 2);
- r->ur_tgtlen = req->rq_reqmsg->buflens[offset + 2];
- 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_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_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_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,
- [REINT_RECREATE] mds_create_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;
- ENTRY;
-
- if (!opcode || req->rq_reqmsg->buflens[offset] < sizeof(*opcode))
- RETURN(-EFAULT);
-
- rec->ur_opcode = NTOH__u32(*opcode);
-
- if (rec->ur_opcode < 0 || rec->ur_opcode > REINT_MAX)
- RETURN(-EFAULT);
-
- rc = mds_unpackers[rec->ur_opcode](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 *md, int bufcnt)
-{
- struct obd_ioobj *ioo = *tmp;
- char *c = *tmp;
-
- ioo->ioo_id = HTON__u64(md->lmd_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:
- *
- * 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/locks.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_OST
-
-#include <linux/obd_class.h>
-#include <linux/lustre_net.h>
-#include <linux/lustre_lib.h>
-#include <linux/lustre_ha.h>
-
-static int sync_io_timeout(void *data)
-{
- struct io_cb_data *cbd = data;
- struct ptlrpc_bulk_desc *desc = cbd->desc;
-
- ENTRY;
- desc->b_connection->c_level = LUSTRE_CONN_RECOVD;
- desc->b_flags |= PTL_RPC_FL_TIMEOUT;
- if (desc->b_client && desc->b_client->cli_recovd) {
- /* XXXshaver Do we need a resend strategy, or do we just
- * XXXshaver return -ERESTARTSYS and punt it?
- */
-#if 0
- recovd_cli_fail(desc->b_client);
-#endif
- }
-
- /* We go back to sleep, until we're resumed or interrupted. */
- RETURN(0);
-}
-
-static int sync_io_intr(void *data)
-{
- struct io_cb_data *cbd = data;
- struct ptlrpc_bulk_desc *desc = cbd->desc;
-
- ENTRY;
- desc->b_flags |= PTL_RPC_FL_INTR;
- RETURN(1); /* ignored, as of this writing */
-}
-
-int ll_sync_io_cb(struct io_cb_data *data, int err, int phase)
-{
- int ret;
- ENTRY;
-
- if (phase == CB_PHASE_START) {
-#warning shaver hardcoded timeout
- struct l_wait_info lwi;
- lwi = LWI_TIMEOUT_INTR(100, sync_io_timeout,
- SIGTERM | SIGKILL | SIGINT, sync_io_intr,
- data);
- ret = l_wait_event(data->waitq, data->complete, &lwi);
- if (atomic_dec_and_test(&data->refcount))
- OBD_FREE(data, sizeof(*data));
- if (ret == -ERESTARTSYS)
- return ret;
- } else if (phase == CB_PHASE_FINISH) {
- data->err = err;
- data->complete = 1;
- wake_up(&data->waitq);
- if (atomic_dec_and_test(&data->refcount))
- OBD_FREE(data, sizeof(*data));
- return err;
- } else
- LBUG();
- EXIT;
- return 0;
-}
-
-struct io_cb_data *ll_init_cb(void)
-{
- struct io_cb_data *d;
-
-
- OBD_ALLOC(d, sizeof(*d));
- if (d) {
- init_waitqueue_head(&d->waitq);
- atomic_set(&d->refcount, 2);
- }
- RETURN(d);
-}
-
-/*
- * 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,4,9))
- 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,4,10))
- spin_unlock(&pagecache_lock);
-#endif
- EXIT;
-}
-
-inline void set_page_clean(struct page *page)
-{
- if (PageDirty(page)) {
- ClearPageDirty(page);
- __set_page_clean(page);
- }
-}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10))
-/*
- * Add a page to the dirty page list.
- */
-void __set_page_dirty(struct page *page)
-{
- struct address_space *mapping;
- spinlock_t *pg_lock;
-
- pg_lock = PAGECACHE_LOCK(page);
- spin_lock(pg_lock);
-
- mapping = page->mapping;
- spin_lock(&mapping->page_lock);
-
- list_del(&page->list);
- list_add(&page->list, &mapping->dirty_pages);
-
- spin_unlock(&mapping->page_lock);
- spin_unlock(pg_lock);
-
- if (mapping->host)
- mark_inode_dirty_pages(mapping->host);
-}
-#else
-/*
- * Add a page to the dirty page list.
- */
-void set_page_dirty(struct page *page)
-{
- if (!test_and_set_bit(PG_dirty, &page->flags)) {
- struct address_space *mapping = page->mapping;
-
- if (mapping) {
- spin_lock(&pagecache_lock);
- list_del(&page->list);
- list_add(&page->list, &mapping->dirty_pages);
- spin_unlock(&pagecache_lock);
-
- if (mapping->host)
- mark_inode_dirty_pages(mapping->host);
- }
- }
-}
-#endif
-
-inline void lustre_put_page(struct page *page)
-{
- kunmap(page);
- page_cache_release(page);
-}
-
-struct page *lustre_get_page_read(struct inode *inode, unsigned long index)
-{
- 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 (!Page_Uptodate(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);
-}
-
-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);
-}
-
-int lustre_commit_write(struct page *page, unsigned from, unsigned to)
-{
- struct inode *inode = page->mapping->host;
- int err = 0;
-
- SetPageUptodate(page);
- set_page_clean(page);
-
- page->mapping->a_ops->commit_write(NULL, page, from, to);
- if (IS_SYNC(inode))
- err = waitfor_one_page(page);
- UnlockPage(page);
- lustre_put_page(page);
- return err;
-}
+++ /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/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)
-{
- //ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
- ASSERT_CTXT_MAGIC(new->magic);
- OBD_SET_CTXT_MAGIC(save);
- save->fs = get_fs();
- save->pwd = dget(current->fs->pwd);
- save->pwdmnt = mntget(current->fs->pwdmnt);
-
- set_fs(new->fs);
- set_fs_pwd(current->fs, new->pwdmnt, new->pwd);
-}
-
-void pop_ctxt(struct obd_run_ctxt *saved)
-{
- ASSERT_KERNEL_CTXT("popping non-kernel context!\n");
- ASSERT_CTXT_MAGIC(saved->magic);
- set_fs(saved->fs);
- set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
-
- dput(saved->pwd);
- mntput(saved->pwdmnt);
-}
-
-/* utility to make a directory */
-struct dentry *simple_mkdir(struct dentry *dir, char *name, int mode)
-{
- struct dentry *dchild;
- int err;
- ENTRY;
-
- ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
- CDEBUG(D_INODE, "creating directory %*s\n", strlen(name), name);
- dchild = lookup_one_len(name, dir, strlen(name));
- if (IS_ERR(dchild))
- RETURN(dchild);
-
- if (dchild->d_inode) {
- if (!S_ISDIR(dchild->d_inode->i_mode))
- GOTO(out, err = -ENOTDIR);
-
- RETURN(dchild);
- }
-
- err = vfs_mkdir(dir->d_inode, dchild, mode);
- EXIT;
-out:
- 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
-.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
-
-page.c:
- test -e page.c || ln -sf $(top_srcdir)/lib/page.c
-
-
-LINX=page.c
-llite_SOURCES = dcache.c recover.c commit_callback.c page.c super.c rw.c file.c dir.c sysctl.c namei.c symlink.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:
- *
- * 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/locks.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();
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
-
- sprintf(current->comm, "lustre_commitcbd");
-
- /* 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:
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
- *
- */
-
-#include <linux/fs.h>
-#include <linux/locks.h>
-#include <linux/quotaops.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;
-
-void ll_intent_release(struct dentry *de)
-{
- struct lustre_handle *handle;
- ENTRY;
-
- if (de->d_it == NULL) {
- EXIT;
- return;
- }
- if (de->d_it->it_lock_mode) {
- handle = (struct lustre_handle *)de->d_it->it_lock_handle;
- if (de->d_it->it_op == IT_SETATTR) {
- int rc;
- ldlm_lock_decref(handle, de->d_it->it_lock_mode);
- rc = ldlm_cli_cancel(handle);
- if (rc < 0)
- CERROR("ldlm_cli_cancel: %d\n", rc);
- } else
- ldlm_lock_decref(handle, de->d_it->it_lock_mode);
- }
- de->d_it = NULL;
- EXIT;
-}
-
-int ll_revalidate2(struct dentry *de, int flags, struct lookup_intent *it)
-{
- ENTRY;
-
- RETURN(0);
-}
-
-struct dentry_operations ll_d_ops = {
- d_revalidate2: ll_revalidate2,
- d_intent_release: ll_intent_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/locks.h>
-#include <asm/uaccess.h>
-
-#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 lookup_intent it = {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 = ll_lock(inode, NULL, &it, &lockh);
- request = (struct ptlrpc_request *)it.it_data;
- ptlrpc_free_req(request);
- if (rc != ELDLM_OK) {
- CERROR("lock enqueue: err: %d\n", rc);
- UnlockPage(page);
- RETURN(rc);
- }
- ldlm_lock_dump((void *)(unsigned long)lockh.addr);
-
- if (Page_Uptodate(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);
- ptlrpc_free_req(request);
- EXIT;
-
- readpage_out:
- if ( !rc )
- SetPageUptodate(page);
-
- UnlockPage(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
-};
-
-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;
-}
-
-/*
- * 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 * ext2_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 (!Page_Uptodate(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 = ext2_get_page(inode, n);
-
- 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 = ext2_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 = ext2_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);
- UnlockPage(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 = ext2_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:
- UnlockPage(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);
- UnlockPage(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);
- UnlockPage(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 = ext2_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>
-
-int ll_inode_setattr(struct inode *inode, struct iattr *attr, int do_trunc);
-extern int ll_setattr(struct dentry *de, struct iattr *attr);
-
-static int ll_file_open(struct inode *inode, struct file *file)
-{
- int rc;
- struct ptlrpc_request *req = NULL;
- struct ll_file_data *fd;
- struct obdo *oa = NULL;
- struct lov_stripe_md *md = NULL;
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ll_inode_info *lli = ll_i2info(inode);
- ENTRY;
-
- if (file->private_data)
- LBUG();
-
- /* delayed create of object (intent created inode) */
- /* XXX object needs to be cleaned up if mdc_open fails */
- /* XXX error handling appropriate here? */
- if (lli->lli_smd == NULL) {
- struct client_obd *mdc = sbi2mdc(ll_s2sbi(inode->i_sb));
- struct inode * inode = file->f_dentry->d_inode;
-
- down(&lli->lli_open_sem);
- /* Check to see if we lost the race */
- if (lli->lli_smd == NULL) {
- oa = obdo_alloc();
- if (!oa) {
- up(&lli->lli_open_sem);
- RETURN(-ENOMEM);
- }
- oa->o_mode = S_IFREG | 0600;
- oa->o_easize = mdc->cl_max_mdsize;
- oa->o_valid = OBD_MD_FLMODE | OBD_MD_FLEASIZE;
- rc = obd_create(ll_i2obdconn(inode), oa, &lli->lli_smd);
- if (rc) {
- obdo_free(oa);
- up(&lli->lli_open_sem);
- RETURN(rc);
- }
- md = lli->lli_smd;
- }
- if (lli->lli_smd && lli->lli_smd->lmd_object_id == 0)
- LBUG();
- up(&lli->lli_open_sem);
- }
-
- fd = kmem_cache_alloc(ll_file_data_slab, SLAB_KERNEL);
- if (!fd)
- GOTO(out, rc = -ENOMEM);
- memset(fd, 0, sizeof(*fd));
-
- rc = mdc_open(&sbi->ll_mdc_conn, inode->i_ino, S_IFREG | inode->i_mode,
- file->f_flags, md,
- (__u64)(unsigned long)file, &fd->fd_mdshandle, &req);
- fd->fd_req = req;
- ptlrpc_req_finished(req);
- if (rc)
- GOTO(out_req, -abs(rc));
- if (!fd->fd_mdshandle) {
- CERROR("mdc_open didn't assign fd_mdshandle\n");
- /* XXX handle this how, abort or is it non-fatal? */
- }
- if (!fd->fd_mdshandle)
- CERROR("mdc_open didn't assign fd_mdshandle\n");
-
- if (oa == NULL && (oa = obdo_alloc()) == NULL)
- GOTO(out_mdc, rc = -EINVAL);
-
- oa->o_id = lli->lli_smd->lmd_object_id;
- oa->o_mode = S_IFREG | inode->i_mode;
- oa->o_valid = OBD_MD_FLMODE | OBD_MD_FLID;
- rc = obd_open(ll_i2obdconn(inode), oa, lli->lli_smd);
- obdo_free(oa);
- oa = NULL;
-
- if (rc)
- GOTO(out_mdc, rc = -abs(rc));
-
- file->private_data = fd;
-
- EXIT;
-
- return 0;
-out_mdc:
- mdc_close(&sbi->ll_mdc_conn, inode->i_ino,
- S_IFREG, fd->fd_mdshandle, &req);
-out_req:
- ptlrpc_free_req(req);
-//out_fd:
- obdo_free(oa);
- kmem_cache_free(ll_file_data_slab, fd);
- file->private_data = NULL;
-out:
- return rc;
-}
-
-static int ll_file_release(struct inode *inode, struct file *file)
-{
- int rc;
- 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);
-
- ENTRY;
-
- fd = (struct ll_file_data *)file->private_data;
- if (!fd || !fd->fd_mdshandle) {
- LBUG();
- GOTO(out, rc = -EINVAL);
- }
-
- oa = obdo_alloc();
- if (oa == NULL) {
- LBUG();
- GOTO(out_fd, rc = -ENOENT);
- }
- oa->o_id = lli->lli_smd->lmd_object_id;
- oa->o_mode = S_IFREG;
- oa->o_valid = (OBD_MD_FLMODE | OBD_MD_FLID);
- rc = obd_close(ll_i2obdconn(inode), oa, lli->lli_smd);
- obdo_free(oa);
- if (rc)
- GOTO(out_fd, abs(rc));
-
- if (file->f_mode & FMODE_WRITE) {
- 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 = inode->i_size;
-
- /* XXX: this introduces a small race that we should evaluate */
- rc = ll_inode_setattr(inode, &attr, 0);
- if (rc) {
- CERROR("failed - %d.\n", rc);
- rc = -EIO; /* XXX - GOTO(out)? -phil */
- }
- }
-
- rc = mdc_close(&sbi->ll_mdc_conn, inode->i_ino,
- S_IFREG, fd->fd_mdshandle, &req);
- ptlrpc_req_finished(req);
- if (rc) {
- if (rc > 0)
- rc = -rc;
- GOTO(out, rc);
- }
- ptlrpc_free_req(fd->fd_req);
-
- EXIT;
-
-out_fd:
- kmem_cache_free(ll_file_data_slab, fd);
- file->private_data = NULL;
-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);
-}
-
-static int ll_lock_callback(struct ldlm_lock *lock, struct ldlm_lock_desc *new,
- void *data, __u32 data_len)
-{
- struct inode *inode = data;
- struct lustre_handle lockh;
- int rc;
- ENTRY;
-
- if (data_len != sizeof(struct inode))
- LBUG();
-
- /* FIXME: do something better than throwing away everything */
- if (inode == NULL)
- LBUG();
- down(&inode->i_sem);
- CDEBUG(D_INODE, "invalidating obdo/inode %ld\n", inode->i_ino);
- invalidate_inode_pages(inode);
- up(&inode->i_sem);
-
- ldlm_lock2handle(lock, &lockh);
- rc = ldlm_cli_cancel(&lockh);
- if (rc != ELDLM_OK)
- CERROR("ldlm_cli_cancel failed: %d\n", rc);
- 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 ldlm_extent extent;
- struct lustre_handle *lockhs = NULL;
- struct lov_stripe_md *md = ll_i2info(inode)->lli_smd;
- int flags = 0;
- ldlm_error_t err;
- ssize_t retval;
- ENTRY;
-
-
-
- if (!(fd->fd_flags & LL_FILE_IGNORE_LOCK)) {
- OBD_ALLOC(lockhs, md->lmd_stripe_count * sizeof(*lockhs));
- if (!lockhs)
- RETURN(-ENOMEM);
-
- extent.start = *ppos;
- extent.end = *ppos + count;
- CDEBUG(D_INFO, "Locking inode %ld, start %Lu end %Lu\n",
- inode->i_ino, extent.start, extent.end);
-
- err = obd_enqueue(&sbi->ll_osc_conn, md, NULL, LDLM_EXTENT,
- &extent, sizeof(extent), LCK_PR, &flags,
- ll_lock_callback, inode, sizeof(*inode),
- lockhs);
- if (err != ELDLM_OK) {
- OBD_FREE(lockhs, md->lmd_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)) {
- err = obd_cancel(&sbi->ll_osc_conn, md, LCK_PR, lockhs);
- if (err != ELDLM_OK) {
- OBD_FREE(lockhs, md->lmd_stripe_count * sizeof(*lockhs));
- CERROR("lock cancel: err: %d\n", err);
- RETURN(err);
- }
- }
-
- if (lockhs)
- OBD_FREE(lockhs, md->lmd_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 ldlm_extent extent;
- struct lustre_handle *lockhs = NULL;
- struct lov_stripe_md *md = ll_i2info(inode)->lli_smd;
- int flags = 0;
- ldlm_error_t err;
- ssize_t retval;
- ENTRY;
-
- if (!(fd->fd_flags & LL_FILE_IGNORE_LOCK)) {
- OBD_ALLOC(lockhs, md->lmd_stripe_count * sizeof(*lockhs));
- if (!lockhs)
- RETURN(-ENOMEM);
- /* FIXME: this should check whether O_APPEND is set and adjust
- * extent.start accordingly */
- extent.start = *ppos;
- extent.end = *ppos + count;
- CDEBUG(D_INFO, "Locking inode %ld, start %Lu end %Lu\n",
- inode->i_ino, extent.start, extent.end);
-
- err = obd_enqueue(&sbi->ll_osc_conn, md, NULL, LDLM_EXTENT,
- &extent, sizeof(extent), LCK_PW, &flags,
- ll_lock_callback, inode, sizeof(*inode),
- lockhs);
- if (err != ELDLM_OK) {
- OBD_FREE(lockhs, md->lmd_stripe_count * sizeof(*lockhs));
- CERROR("lock enqueue: err: %d\n", err);
- RETURN(err);
- }
- }
-
- CDEBUG(D_INFO, "Writing inode %ld, %ld bytes, offset %Ld\n",
- inode->i_ino, (long)count, *ppos);
-
- retval = generic_file_write(file, buf, count, ppos);
-
- if (!(fd->fd_flags & LL_FILE_IGNORE_LOCK)) {
- err = obd_cancel(&sbi->ll_osc_conn, md, LCK_PW, lockhs);
- if (err != ELDLM_OK) {
- OBD_FREE(lockhs, md->lmd_stripe_count * sizeof(*lockhs));
- CERROR("lock cancel: err: %d\n", err);
- RETURN(err);
- }
- }
-
- if (lockhs)
- OBD_FREE(lockhs, md->lmd_stripe_count * sizeof(*lockhs));
- RETURN(retval);
-}
-
-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;
- 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;
-
- /* 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:
- return -ENOTTY;
- }
-}
-
-/* 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;
-}
-
-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,
- fsync: NULL
-};
-
-struct inode_operations ll_file_inode_operations = {
- truncate: ll_truncate,
- setattr: ll_setattr
-};
+++ /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/locks.h>
-#include <linux/quotaops.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 */
-static int ll_find_inode(struct inode *inode, unsigned long ino, void *opaque)
-{
- struct mds_body *body = (struct mds_body *)opaque;
-
- if (inode->i_generation != body->generation)
- return 0;
-
- return 1;
-}
-
-extern struct dentry_operations ll_d_ops;
-
-int ll_lock(struct inode *dir, struct dentry *dentry,
- struct lookup_intent *it, struct lustre_handle *lockh)
-{
- struct ll_sb_info *sbi = ll_i2sbi(dir);
- int err, lock_mode;
-
- if ((it->it_op & (IT_CREAT | IT_MKDIR | IT_SYMLINK | IT_SETATTR |
- IT_MKNOD)))
- lock_mode = LCK_PW;
- else if (it->it_op & (IT_READDIR | IT_GETATTR | IT_OPEN | IT_UNLINK |
- IT_RMDIR | IT_RENAME | IT_RENAME2 | IT_READLINK))
- lock_mode = LCK_PR;
- else if (it->it_op & IT_LOOKUP)
- lock_mode = LCK_CR;
- else {
- LBUG();
- RETURN(-EINVAL);
- }
-
-#warning FIXME: add symlink tgt to intent and as a parameter here
- err = mdc_enqueue(&sbi->ll_mdc_conn, LDLM_MDSINTENT, it, lock_mode, dir,
- dentry, lockh, 0, NULL, 0, dir, sizeof(*dir));
-
- RETURN(err);
-}
-
-int ll_unlock(__u32 mode, struct lustre_handle *lockh)
-{
- ENTRY;
-
- ldlm_lock_decref(lockh, mode);
-
- RETURN(0);
-}
-
-static struct dentry *ll_lookup2(struct inode * dir, struct dentry *dentry,
- struct lookup_intent *it)
-{
- struct ptlrpc_request *request = NULL;
- struct inode * inode = NULL;
- struct ll_sb_info *sbi = ll_i2sbi(dir);
- struct ll_inode_md md;
- struct lustre_handle lockh;
- int err, offset;
- struct lookup_intent lookup_it = { IT_LOOKUP };
- obd_id ino = 0;
-
- ENTRY;
-
- if (it == NULL) {
- it = &lookup_it;
- dentry->d_it = it;
- }
-
- CDEBUG(D_INFO, "name: %*s, intent op: %d\n", dentry->d_name.len,
- dentry->d_name.name, it->it_op);
-
- if (dentry->d_name.len > EXT2_NAME_LEN)
- RETURN(ERR_PTR(-ENAMETOOLONG));
-
- err = ll_lock(dir, dentry, it, &lockh);
- if (err < 0)
- RETURN(ERR_PTR(err));
- memcpy(it->it_lock_handle, &lockh, sizeof(lockh));
-
- if (it->it_disposition) {
- offset = 1;
- if (it->it_op & (IT_CREAT | IT_MKDIR | IT_SYMLINK | IT_MKNOD)) {
- /* For create ops, we want the lookup to be negative */
- request = (struct ptlrpc_request *)it->it_data;
- if (!it->it_status)
- GOTO(negative, NULL);
- //else
- // GOTO(err, it->it_status);
- } else if (it->it_op & (IT_RENAME | IT_GETATTR | IT_UNLINK |
- IT_RMDIR | IT_SETATTR | IT_LOOKUP)) {
- /* For remove/check, we want the lookup to succeed */
- request = (struct ptlrpc_request *)it->it_data;
- if (it->it_status)
- GOTO(neg_req, NULL);
- //else
- // GOTO(err, it->it_status);
- } else if (it->it_op == IT_OPEN) {
- request = (struct ptlrpc_request *)it->it_data;
- if (it->it_status && it->it_status != -EEXIST)
- GOTO(neg_req, NULL);
- } else if (it->it_op == IT_RENAME2) {
- /* Set below to be a dentry from the IT_RENAME op */
- inode = ((struct dentry *)(it->it_data))->d_inode;
- GOTO(out_req, NULL);
- }
- } else {
- struct ll_inode_info *lli = ll_i2info(dir);
- int type;
-
- request = (struct ptlrpc_request *)it->it_data;
- memcpy(&lli->lli_intent_lock_handle, &lockh, sizeof(lockh));
- offset = 0;
-
- ino = ll_inode_by_name(dir, dentry, &type);
-#warning FIXME: handle negative inode case (see old ll_lookup)
-
- err = mdc_getattr(&sbi->ll_mdc_conn, ino, type,
- OBD_MD_FLNOTOBD|OBD_MD_FLEASIZE, 0, &request);
- if (err) {
- CERROR("failure %d inode %Ld\n", err, (long long)ino);
- ptlrpc_free_req(request);
- RETURN(ERR_PTR(-abs(err)));
- }
- }
-
- md.body = lustre_msg_buf(request->rq_repmsg, offset);
- if (S_ISREG(md.body->mode)) {
- if (request->rq_repmsg->bufcount < offset + 1)
- LBUG();
- md.md = lustre_msg_buf(request->rq_repmsg, offset + 1);
- } else
- md.md = NULL;
-
- /* No rpc's happen during iget4, -ENOMEM's are possible */
- inode = iget4(dir->i_sb, ino, ll_find_inode, &md);
- if (it->it_op & IT_RENAME)
- it->it_data = dentry;
-
- out_req:
- if (!inode || IS_ERR(inode)) {
- ptlrpc_free_req(request);
- request = it->it_data = NULL;
- ll_intent_release(dentry);
- RETURN(inode ? (struct dentry *)inode : ERR_PTR(-ENOMEM));
- }
- EXIT;
- neg_req:
- ptlrpc_free_req(request);
- request = it->it_data = NULL;
- negative:
- dentry->d_op = &ll_d_ops;
- d_add(dentry, inode);
- if (it->it_op == IT_LOOKUP)
- ll_intent_release(dentry);
-
- return NULL;
-}
-
-static struct inode *ll_create_node(struct inode *dir, const char *name,
- int namelen, const char *tgt, int tgtlen,
- int mode, __u64 extra,
- struct lookup_intent *it,
- struct lov_stripe_md *smd)
-{
- struct inode *inode;
- struct ptlrpc_request *request = NULL;
- struct mds_body *body;
- int rc;
- time_t time = CURRENT_TIME;
- struct ll_sb_info *sbi = ll_i2sbi(dir);
- int gid = current->fsgid;
- struct ll_inode_md md;
-
- ENTRY;
-
- if (dir->i_mode & S_ISGID) {
- gid = dir->i_gid;
- if (S_ISDIR(mode))
- mode |= S_ISGID;
- }
-
- if (!it || !it->it_disposition) {
- rc = mdc_create(&sbi->ll_mdc_conn, dir, name, namelen, tgt,
- tgtlen, mode, current->fsuid,
- gid, time, extra, smd, &request);
- if (rc) {
- inode = ERR_PTR(rc);
- GOTO(out, rc);
- }
- body = lustre_msg_buf(request->rq_repmsg, 0);
- md.md = smd;
- } else {
- request = it->it_data;
- body = lustre_msg_buf(request->rq_repmsg, 1);
- md.md = NULL;
- }
-
- body->valid = OBD_MD_FLNOTOBD;
-
- body->nlink = 1;
- body->atime = body->ctime = body->mtime = time;
- body->uid = current->fsuid;
- body->gid = gid;
- body->mode = mode;
-
- md.body = body;
-
- inode = iget4(dir->i_sb, body->ino, ll_find_inode, &md);
- if (IS_ERR(inode)) {
- 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);
- }
-
- EXIT;
- out:
- ptlrpc_free_req(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_free_req(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_free_req(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_free_req(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.
- *
- * 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)
-{
- int err, rc = 0;
- struct obdo oa;
- struct inode *inode;
- struct lov_stripe_md *smd;
- struct ll_inode_info *ii = NULL;
- ENTRY;
-
- if (dentry->d_it->it_disposition == 0) {
- memset(&oa, 0, sizeof(oa));
- oa.o_valid = OBD_MD_FLMODE;
- oa.o_mode = S_IFREG | 0600;
- rc = obd_create(ll_i2obdconn(dir), &oa, &smd);
- CDEBUG(D_DENTRY, "name %s mode %o o_id %lld: rc = %d\n",
- dentry->d_name.name, mode, (long long)oa.o_id, rc);
- if (rc)
- RETURN(rc);
- }
-
- inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
- NULL, 0, mode, 0, dentry->d_it, smd);
-
- if (IS_ERR(inode)) {
- rc = PTR_ERR(inode);
- CERROR("error creating MDS object for id %Ld: rc = %d\n",
- (unsigned long long)oa.o_id, rc);
-#warning FIXME: 'ii' needs to be set before this goto
- GOTO(out_destroy, rc);
- }
-
- if (dentry->d_it->it_disposition) {
- ii = ll_i2info(inode);
- memcpy(&ii->lli_intent_lock_handle,
- dentry->d_it->it_lock_handle,
- sizeof(struct lustre_handle));
- d_instantiate(dentry, inode);
- } else {
- /* no directory data updates when intents rule */
- rc = ext2_add_nondir(dentry, inode);
- }
-
- RETURN(rc);
-
-out_destroy:
-#warning FIXME: what about ii???
- oa.o_easize = ii->lli_smd->lmd_easize;
- err = obd_destroy(ll_i2obdconn(dir), &oa, ii->lli_smd);
- if (err)
- CERROR("error destroying object %Ld in error path: err = %d\n",
- (unsigned long long)oa.o_id, err);
- return rc;
-}
-
-static int ll_mknod(struct inode *dir, struct dentry *dentry, int mode,
- int rdev)
-{
- struct inode *inode;
- int err = 0;
-
- inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
- NULL, 0, mode, rdev, dentry->d_it, NULL);
-
- if (IS_ERR(inode))
- RETURN(PTR_ERR(inode));
-
- /* no directory data updates when intents rule */
- if (dentry->d_it->it_disposition == 0)
- err = ext2_add_nondir(dentry, inode);
- else
- d_instantiate(dentry, inode);
-
- return err;
-}
-
-static int ll_symlink(struct inode *dir, struct dentry *dentry,
- const char *symname)
-{
- unsigned l = strlen(symname);
- struct inode *inode;
- struct ll_inode_info *oinfo;
-
- inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
- symname, l, S_IFLNK | S_IRWXUGO, 0,
- dentry->d_it, NULL);
- if (IS_ERR(inode))
- RETURN(PTR_ERR(inode));
-
- oinfo = ll_i2info(inode);
-
- if (dentry->d_it->it_disposition) {
-#warning FIXME: still needs intent support
- d_instantiate(dentry, inode);
- return 0;
- }
-
- OBD_ALLOC(oinfo->lli_symlink_name, l + 1);
- if (!oinfo->lli_symlink_name)
- RETURN(-ENOMEM);
-
- memcpy(oinfo->lli_symlink_name, symname, l + 1);
- inode->i_size = l;
-
- return ext2_add_nondir(dentry, inode);
-}
-
-static int ll_link(struct dentry *old_dentry, struct inode * dir,
- struct dentry *dentry)
-{
- int err;
- struct inode *inode = old_dentry->d_inode;
-
-#warning FIXME: still needs intent support
- if (S_ISDIR(inode->i_mode))
- return -EPERM;
-
- if (inode->i_nlink >= EXT2_LINK_MAX)
- return -EMLINK;
-
- err = ll_mdc_link(old_dentry, dir,
- dentry->d_name.name, dentry->d_name.len);
- if (err)
- RETURN(err);
-
- 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 inode * inode;
- int err = -EMLINK;
- ENTRY;
-
- 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, dentry->d_it, NULL);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_dir;
-
- ext2_inc_count(inode);
-
- err = ext2_make_empty(inode, dir);
- if (err)
- goto out_fail;
-
- /* no directory data updates when intents rule */
- if (dentry->d_it->it_disposition == 0) {
- 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,
- __u32 mode)
-{
- struct inode * inode = dentry->d_inode;
- struct ext2_dir_entry_2 * de;
- struct page * page;
- int err = -ENOENT;
-
- if (dentry->d_it && dentry->d_it->it_disposition) {
- err = dentry->d_it->it_status;
- if (!err)
- inode->i_nlink = 0;
- GOTO(out, err);
- }
-
- de = ext2_find_entry(dir, dentry, &page);
- if (!de)
- goto out;
-
- err = ll_mdc_unlink(dir, dentry->d_inode, mode,
- dentry->d_name.name, dentry->d_name.len);
- if (err)
- goto out;
-
- err = ext2_delete_entry(de, page);
- if (err)
- goto out;
-
- inode->i_ctime = dir->i_ctime;
- ext2_dec_count(inode);
-out:
- return err;
-}
-
-static int ll_unlink(struct inode *dir, struct dentry *dentry)
-{
- return ll_common_unlink(dir, dentry, S_IFREG);
-}
-
-static int ll_rmdir(struct inode *dir, struct dentry *dentry)
-{
- struct inode * inode = dentry->d_inode;
- int err = 0;
- ENTRY;
-
- if (!dentry->d_it || dentry->d_it->it_disposition == 0) {
- if (!ext2_empty_dir(inode))
- LBUG();
-
- err = ll_common_unlink(dir, dentry, S_IFDIR);
- } else
- err = dentry->d_it->it_status;
- if (err)
- RETURN(err);
- inode->i_size = 0;
- ext2_dec_count(inode);
- ext2_dec_count(dir);
- RETURN(err);
-}
-
-static int ll_rename(struct inode * old_dir, struct dentry * old_dentry,
- struct inode * new_dir, struct dentry * new_dentry)
-{
- struct inode * old_inode = old_dentry->d_inode;
- struct inode * new_inode = new_dentry->d_inode;
- struct page * dir_page = NULL;
- struct ext2_dir_entry_2 * dir_de = NULL;
- struct page * old_page;
- struct ext2_dir_entry_2 * old_de;
- int err = -ENOENT;
-
- if (new_dentry->d_it && new_dentry->d_it->it_disposition)
- GOTO(out, err = new_dentry->d_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 (new_inode) {
- struct page *new_page;
- struct ext2_dir_entry_2 *new_de;
-
- err = -ENOTEMPTY;
- if (dir_de && !ext2_empty_dir (new_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);
- new_inode->i_ctime = CURRENT_TIME;
- if (dir_de)
- new_inode->i_nlink--;
- ext2_dec_count(new_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 Light Super operations
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copryright (C) 1996 Peter J. Braam <braam@stelias.com>
- * Copryright (C) 1999 Stelias Computing Inc. <braam@stelias.com>
- * Copryright (C) 1999 Seagate Technology Inc.
- * Copryright (C) 2001 Mountain View Data, Inc.
- * Copryright (C) 2002 Cluster File Systems, Inc.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/lustre_lite.h>
-#include <linux/lustre_ha.h>
-
-
-static int ll_reconnect(struct ll_sb_info *sbi)
-{
- struct ll_fid rootfid;
- __u64 last_committed;
- __u32 last_xid;
- int err;
- struct ptlrpc_request *request;
-
- ptlrpc_readdress_connection(sbi2mdc(sbi)->cl_conn, "mds");
-
- err = connmgr_connect(ptlrpc_connmgr, sbi2mdc(sbi)->cl_conn);
- if (err) {
- CERROR("cannot connect to MDS: rc = %d\n", err);
- ptlrpc_put_connection(sbi2mdc(sbi)->cl_conn);
- GOTO(out_disc, err = -ENOTCONN);
- }
- sbi2mdc(sbi)->cl_conn->c_level = LUSTRE_CONN_CON;
-
- /* XXX: need to store the last_* values somewhere */
- err = mdc_getstatus(&sbi->ll_mdc_conn,
- &rootfid, &last_committed,
- &last_xid,
- &request);
- if (err) {
- CERROR("cannot mds_connect: rc = %d\n", err);
- GOTO(out_disc, err = -ENOTCONN);
- }
- sbi2mdc(sbi)->cl_client->cli_last_xid = last_xid;
- sbi2mdc(sbi)->cl_conn->c_level = LUSTRE_CONN_RECOVD;
-
- out_disc:
- return err;
-}
-
-
-int ll_recover(struct ptlrpc_client *cli)
-{
- struct ptlrpc_request *req;
- struct list_head *tmp, *pos;
- struct ll_sb_info *sbi = cli->cli_data;
- int rc = 0;
- ENTRY;
-
- /* 1. reconnect */
- ll_reconnect(sbi);
-
- /* 2. walk the request list */
- spin_lock(&cli->cli_lock);
- list_for_each_safe(tmp, pos, &cli->cli_sending_head) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
-
- /* replay what needs to be replayed */
- if (req->rq_flags & PTL_RPC_FL_REPLAY) {
- CDEBUG(D_INODE, "req %Ld needs replay [last rcvd %Ld]\n",
- req->rq_xid, cli->cli_last_xid);
- rc = ptlrpc_replay_req(req);
- if (rc) {
- CERROR("recovery replay error %d for request %Ld\n",
- rc, req->rq_xid);
- GOTO(out, rc);
- }
- }
-
- /* server has seen req, we have reply: skip */
- if ((req->rq_flags & PTL_RPC_FL_REPLIED) &&
- req->rq_xid <= cli->cli_last_xid) {
- CDEBUG(D_INODE, "req %Ld was complete: skip [last rcvd %Ld]\n",
- req->rq_xid, cli->cli_last_xid);
- continue;
- }
-
- /* server has lost req, we have reply: resend, ign reply */
- if ((req->rq_flags & PTL_RPC_FL_REPLIED) &&
- req->rq_xid > cli->cli_last_xid) {
- CDEBUG(D_INODE, "lost req %Ld have rep: replay [last rcvd %Ld]\n",
- req->rq_xid, cli->cli_last_xid);
- rc = ptlrpc_replay_req(req);
- if (rc) {
- CERROR("request resend error %d for request %Ld\n",
- rc, req->rq_xid);
- GOTO(out, rc);
- }
- }
-
- /* server has seen req, we have lost reply: -ERESTARTSYS */
- if ( !(req->rq_flags & PTL_RPC_FL_REPLIED) &&
- req->rq_xid <= cli->cli_last_xid) {
- CDEBUG(D_INODE, "lost rep %Ld srv did req: restart [last rcvd %Ld]\n",
- req->rq_xid, cli->cli_last_xid);
- ptlrpc_restart_req(req);
- }
-
- /* service has not seen req, no reply: resend */
- if ( !(req->rq_flags & PTL_RPC_FL_REPLIED) &&
- req->rq_xid > cli->cli_last_xid) {
- CDEBUG(D_INODE, "lost rep/req %Ld: resend [last rcvd %Ld]\n",
- req->rq_xid, cli->cli_last_xid);
- ptlrpc_resend_req(req);
- }
-
- }
-
- sbi2mdc(sbi)->cl_conn->c_level = LUSTRE_CONN_FULL;
- recovd_cli_fixed(cli);
-
- /* Finally, continue what we delayed since recovery started */
- list_for_each_safe(tmp, pos, &cli->cli_delayed_head) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
- ptlrpc_continue_req(req);
- }
-
- EXIT;
- out:
- spin_unlock(&cli->cli_lock);
- return rc;
-}
+++ /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) 2002 Cluster File Systems, Inc.
- */
-
-#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/locks.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>
-
-
-/* SYNCHRONOUS I/O to object storage for an inode */
-static int ll_brw(int rw, struct inode *inode, struct page *page, int create)
-{
- struct ll_inode_info *lii = ll_i2info(inode);
- struct lov_stripe_md *md = lii->lli_smd;
- struct brw_page pg;
- int err;
- struct io_cb_data *cbd = ll_init_cb();
- ENTRY;
- if (!cbd)
- RETURN(-ENOMEM);
-
- pg.pg = page;
- pg.count = PAGE_SIZE;
- pg.off = ((obd_off)page->index) << PAGE_SHIFT;
- pg.flag = create ? OBD_BRW_CREATE : 0;
-
- err = obd_brw(rw, ll_i2obdconn(inode), md, 1, &pg, ll_sync_io_cb, cbd);
- RETURN(err);
-} /* ll_brw */
-
-/* returns the page unlocked, but with a reference */
-static int ll_readpage(struct file *file, struct page *page)
-{
- struct inode *inode = page->mapping->host;
- int rc = 0;
- ENTRY;
-
- if (!PageLocked(page))
- LBUG();
-
- if (((inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT) <= page->index) {
- memset(kmap(page), 0, PAGE_SIZE);
- kunmap(page);
- GOTO(readpage_out, rc);
- }
-
- if (Page_Uptodate(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);
- UnlockPage(page);
- return 0;
-} /* ll_readpage */
-
-
-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);
-
- memset(addr, 0, PAGE_SIZE);
-
- /* 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);
-
- /* prepare write should not read what lies beyond the end of
- the file */
-
-
- 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);
- }
- UnlockPage(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)
-{
- int create = 1;
- struct inode *inode = page->mapping->host;
- struct ll_inode_info *lii = ll_i2info(inode);
- struct lov_stripe_md *md = lii->lli_smd;
- struct brw_page pg;
- int err;
- struct iattr iattr;
- struct io_cb_data *cbd = ll_init_cb();
-
- pg.pg = page;
- pg.count = to;
- pg.off = (((obd_off)page->index) << PAGE_SHIFT);
- pg.flag = create ? OBD_BRW_CREATE : 0;
-
- ENTRY;
- if (!cbd)
- RETURN(-ENOMEM);
-
- SetPageUptodate(page);
-
- if (!PageLocked(page))
- LBUG();
-
- CDEBUG(D_INODE, "commit_page writing (at %d) to %d, count %Ld\n",
- from, to, (unsigned long long)pg.count);
-
- err = obd_brw(OBD_BRW_WRITE, ll_i2obdconn(inode), md,
- 1, &pg, ll_sync_io_cb, cbd);
- kunmap(page);
-
- iattr.ia_size = pg.off + pg.count;
- if (iattr.ia_size > inode->i_size) {
- /* do NOT truncate when writing in the middle of a file */
- inode->i_size = iattr.ia_size;
- iattr.ia_valid = ATTR_SIZE;
-#if 0
- err = ll_inode_setattr(inode, &iattr, 0);
- if (err) {
- CERROR("failed - %d.\n", err);
- err = -EIO;
- }
-#endif
- }
-
- RETURN(err);
-} /* ll_commit_write */
-
-void ll_truncate(struct inode *inode)
-{
- struct obdo oa = {0};
- struct lov_stripe_md *md = ll_i2info(inode)->lli_smd;
- int err;
- ENTRY;
-
- if (!md) {
- /* object not yet allocated */
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- return;
- }
-
- CDEBUG(D_INFO, "calling punch for %ld (all bytes after %Ld)\n",
- (long)oa.o_id, (unsigned long long)oa.o_size);
-
- oa.o_id = md->lmd_object_id;
- oa.o_valid = OBD_MD_FLID;
- /* truncate == punch to/from start from/to end:
- set end to -1 for that. */
- err = obd_punch(ll_i2obdconn(inode), &oa, md, inode->i_size,
- 0xffffffffffffffff);
- if (err)
- CERROR("obd_truncate fails (%d)\n", err);
- else
- /* This is done for us at the OST and MDS, but the
- * updated timestamps are not sent back to us.
- * Needed for POSIX.
- */
- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-
- EXIT;
- return;
-} /* ll_truncate */
-
-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 *lii = ll_i2info(inode);
- struct lov_stripe_md *md = lii->lli_smd;
- struct brw_page *pga;
- int rc = 0;
- int i;
- struct io_cb_data *cbd = ll_init_cb();
-
- ENTRY;
- if (!cbd)
- RETURN(-ENOMEM);
-
- if (blocksize != PAGE_SIZE) {
- CERROR("direct_IO blocksize != PAGE_SIZE\n");
- return -EINVAL;
- }
-
- OBD_ALLOC(pga, sizeof(*pga) * bufs_per_obdo);
- if (pga)
- GOTO(out, rc = -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;
- }
-
- if (!md || !md->lmd_object_id)
- GOTO(out, rc = -ENOMEM);
-
- rc = obd_brw(rw == WRITE ? OBD_BRW_WRITE : OBD_BRW_READ,
- ll_i2obdconn(inode), md, bufs_per_obdo, pga,
- ll_sync_io_cb, cbd);
- if (rc == 0)
- rc = bufs_per_obdo * PAGE_SIZE;
-
-out:
- 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);
-}
-
-
-
-struct address_space_operations ll_aops = {
- readpage: ll_readpage,
- writepage: ll_writepage,
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,17))
- direct_IO: ll_direct_IO,
-#endif
- sync_page: block_sync_page,
- prepare_write: ll_prepare_write,
- commit_write: ll_commit_write,
- bmap: NULL
-};
+++ /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/lustre_lite.h>
-#include <linux/lustre_ha.h>
-#include <linux/lustre_dlm.h>
-#include <linux/init.h>
-
-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 ptlrpc_client *);
-extern int ll_commitcbd_setup(struct ll_sb_info *);
-extern int ll_commitcbd_cleanup(struct ll_sb_info *);
-
-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 void ll_options(char *options, char **ost, char **mds)
-{
- 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))) )
- 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 statfs sfs;
- __u64 last_committed;
- __u32 last_xid;
- struct ptlrpc_request *request = NULL;
- struct ll_inode_md md;
-
- ENTRY;
- MOD_INC_USE_COUNT;
-
- OBD_ALLOC(sbi, sizeof(*sbi));
- if (!sbi) {
- MOD_DEC_USE_COUNT;
- RETURN(NULL);
- }
-
- sb->u.generic_sbp = sbi;
-
- ll_options(data, &osc, &mdc);
-
- 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);
- }
-
-#if 0
- err = connmgr_connect(ptlrpc_connmgr, sbi->ll_mdc_conn);
- if (err) {
- CERROR("cannot connect to MDC: rc = %d\n", err);
- GOTO(out_rpc, sb = NULL);
- }
-#endif
-
-#warning shaver: might need a cluuid here
- err = obd_connect(&sbi->ll_mdc_conn, obd, NULL);
- if (err) {
- CERROR("cannot connect to %s: rc = %d\n", mdc, err);
- GOTO(out_free, sb = NULL);
- }
- sbi2mdc(sbi)->cl_conn->c_level = LUSTRE_CONN_FULL;
-
- obd = class_uuid2obd(osc);
- if (!obd) {
- CERROR("OSC %s: not setup or attached\n", osc);
- GOTO(out_mdc, sb = NULL);
- }
-#warning shaver: might need a cluuid here
- err = obd_connect(&sbi->ll_osc_conn, obd, NULL);
- if (err) {
- CERROR("cannot connect to %s: rc = %d\n", osc, err);
- GOTO(out_mdc, sb = NULL);
- }
-
- /* XXX: need to store the last_* values somewhere */
- err = mdc_getstatus(&sbi->ll_mdc_conn, &rootfid, &last_committed,
- &last_xid, &request);
- ptlrpc_req_finished(request);
- if (err) {
- CERROR("cannot mds_connect: rc = %d\n", err);
- GOTO(out_mdc, sb = NULL);
- }
- CDEBUG(D_SUPER, "rootfid %Ld\n", (unsigned long long)rootfid.id);
- sbi->ll_rootino = rootfid.id;
-
- memset(&sfs, 0, sizeof(sfs));
- request = NULL;
- err = mdc_statfs(&sbi->ll_mdc_conn, &sfs, &request);
- ptlrpc_req_finished(request);
- sb->s_blocksize = sfs.f_bsize;
- sb->s_blocksize_bits = log2(sfs.f_bsize);
- sb->s_magic = LL_SUPER_MAGIC;
- sb->s_maxbytes = (1ULL << (32 + 9)) - sfs.f_bsize;
-
- sb->s_op = &ll_super_operations;
-
- /* make root inode */
- request = NULL;
- 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);
- }
-
- md.body = lustre_msg_buf(request->rq_repmsg, 0);
- md.md = NULL;
- root = iget4(sb, sbi->ll_rootino, NULL, &md);
-
- 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);
-
-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);
- ENTRY;
- ll_commitcbd_cleanup(sbi);
- obd_disconnect(&sbi->ll_osc_conn);
- 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)
-{
- if (atomic_read(&inode->i_count) == 0) {
- struct ll_inode_info *lli = ll_i2info(inode);
- struct lov_stripe_md *md = lli->lli_smd;
-
- if (md) {
- OBD_FREE(md, md->lmd_easize);
- lli->lli_smd = NULL;
- }
- if (lli->lli_symlink_name) {
- OBD_FREE(lli->lli_symlink_name,
- strlen(lli->lli_symlink_name) + 1);
- lli->lli_symlink_name = NULL;
- }
- }
-}
-
-static void ll_delete_inode(struct inode *inode)
-{
- if (S_ISREG(inode->i_mode)) {
- int err;
- struct obdo *oa;
- struct lov_stripe_md *md = ll_i2info(inode)->lli_smd;
-
- if (!md)
- GOTO(out, -EINVAL);
-
- if (md->lmd_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 = md->lmd_object_id;
- oa->o_easize = md->lmd_easize;
- oa->o_mode = inode->i_mode;
- oa->o_valid = OBD_MD_FLID | OBD_MD_FLEASIZE | OBD_MD_FLMODE;
-
- err = obd_destroy(ll_i2obdconn(inode), oa, md);
- obdo_free(oa);
- CDEBUG(D_SUPER, "obd destroy of %Ld error %d\n",
- md->lmd_object_id, err);
- }
-out:
- clear_inode(inode);
-}
-
-/* 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 ptlrpc_request *request = NULL;
- struct ll_sb_info *sbi = ll_s2sbi(sb);
- int rc;
- ENTRY;
-
- memset(sfs, 0, sizeof(*sfs));
- rc = mdc_statfs(&sbi->ll_mdc_conn, sfs, &request);
- ptlrpc_req_finished(request);
- if (rc)
- CERROR("obd_statfs fails: rc = %d\n", rc);
- else
- CDEBUG(D_SUPER, "statfs shows blocks %ld/%ld objects %ld/%ld\n",
- sfs->f_bavail, sfs->f_blocks, sfs->f_files,sfs->f_ffree);
-
- /* temporary until mds_statfs returns statfs info for all OSTs */
- if (!rc) {
- struct statfs obd_sfs;
-
- rc = obd_statfs(&sbi->ll_osc_conn, &obd_sfs);
- if (rc) {
- CERROR("obd_statfs fails: rc = %d\n", rc);
- GOTO(out, rc);
- }
- CDEBUG(D_SUPER, "obd_statfs returns blocks %ld/%ld, "
- "objects %ld/%ld\n",
- obd_sfs.f_bavail, obd_sfs.f_blocks,
- obd_sfs.f_ffree, obd_sfs.f_files);
-
- sfs->f_bfree = obd_sfs.f_bfree;
- sfs->f_bavail = obd_sfs.f_bavail;
- sfs->f_blocks = obd_sfs.f_blocks;
- if (obd_sfs.f_ffree < sfs->f_ffree)
- sfs->f_ffree = obd_sfs.f_ffree;
- }
-
-out:
- RETURN(rc);
-}
-
-inline int ll_stripe_md_size(struct super_block *sb)
-{
- struct client_obd *mdc = sbi2mdc(ll_s2sbi(sb));
- return mdc->cl_max_mdsize;
-}
-
-static void ll_read_inode2(struct inode *inode, void *opaque)
-{
- struct ll_inode_md *md = opaque;
- struct mds_body *body = md->body;
- struct ll_inode_info *ii = ll_i2info(inode);
- ENTRY;
-
- sema_init(&ii->lli_open_sem, 1);
-
- /* core attributes first */
- 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_FLSIZE)
- inode->i_size = body->size;
- if (body->valid & OBD_MD_FLMODE)
- inode->i_mode = body->mode;
- 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->extra;
- //if (body->valid & OBD_MD_FLEASIZE)
- if (md && md->md && md->md->lmd_stripe_count) {
- struct lov_stripe_md *smd = md->md;
- int size = ll_stripe_md_size(inode->i_sb);
- if (md->md->lmd_easize != size) {
- CERROR("Striping metadata size error %ld\n",
- inode->i_ino);
- LBUG();
- }
- OBD_ALLOC(ii->lli_smd, size);
- if (!ii->lli_smd){
- CERROR("No memory for %d\n", size);
- LBUG();
- }
- memcpy(ii->lli_smd, smd, size);
- }
-
- /* 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;
- }
-
- return;
-}
-
-/* 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
-};
-
-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.0.1, 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);
+++ /dev/null
-/*
- * linux/fs/ext2/symlink.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)
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * ext2 symlink handling code
- *
- * Modified for OBDFS:
- * Copyright (C) 1999 Seagate Technology Inc. (author: braam@stelias.com)
- */
-
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-
-#define DEBUG_SUBSYSTEM S_LLITE
-
-#include <linux/obd_support.h> /* for ENTRY and EXIT only */
-#include <linux/lustre_lite.h>
-
-static int ll_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
- struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode);
- struct ptlrpc_request *request;
- char *tmp;
- int rc, size;
- ENTRY;
-
- rc = mdc_getattr(&sbi->ll_mdc_conn, dentry->d_inode->i_ino, S_IFLNK,
- OBD_MD_LINKNAME, dentry->d_inode->i_size, &request);
- if (rc) {
- CERROR("failure %d inode %ld\n", rc,
- (long)dentry->d_inode->i_ino);
- ptlrpc_free_req(request);
- RETURN(rc);
- }
-
- tmp = lustre_msg_buf(request->rq_repmsg, 1);
- size = MIN(request->rq_repmsg->buflens[1], buflen);
- rc = copy_to_user(buffer, tmp, size);
- if (rc == 0)
- rc = size;
-
- ptlrpc_free_req(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
-};
+++ /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_pack.c
-
-lov_SOURCES = lov_obd.c $(LINX)
-
-lov_pack.c:
- test -e lov_pack.c || ln -sf $(top_srcdir)/lib/lov_pack.c
-
-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>
-
-extern struct obd_device obd_dev[MAX_OBD_DEVICES];
-
-/* obd methods */
-static int lov_connect(struct lustre_handle *conn, struct obd_device *obd,
- char *cluuid)
-{
- struct ptlrpc_request *req;
- struct lov_obd *lov = &obd->u.lov;
- struct lustre_handle mdc_conn;
- uuid_t *uuidarray;
- int rc, rc2;
- int i;
-
- MOD_INC_USE_COUNT;
- rc = class_connect(conn, obd, cluuid);
- if (rc) {
- MOD_DEC_USE_COUNT;
- RETURN(rc);
- }
-
- /* retrieve LOV metadata from MDS */
- rc = obd_connect(&mdc_conn, lov->mdcobd, NULL);
- if (rc) {
- CERROR("cannot connect to mdc: rc = %d\n", rc);
- GOTO(out, rc = -EINVAL);
- }
-
- rc = mdc_getlovinfo(obd, &mdc_conn, &uuidarray, &req);
- rc2 = obd_disconnect(&mdc_conn);
- if (rc || rc2) {
- CERROR("cannot get lov info or disconnect %d/%d\n", rc, rc2);
- GOTO(out, (rc) ? rc : rc2 );
- }
-
- /* sanity... */
- if (strcmp(obd->obd_uuid, lov->desc.ld_uuid)) {
- CERROR("lov uuid %s not on mds device (%s)\n",
- obd->obd_uuid, lov->desc.ld_uuid);
- GOTO(out, rc = -EINVAL);
- }
- if (lov->desc.ld_tgt_count > 1000) {
- CERROR("configuration error: target count > 1000 (%d)\n",
- lov->desc.ld_tgt_count);
- GOTO(out, rc = -EINVAL);
- }
- if (req->rq_repmsg->bufcount < 2 || req->rq_repmsg->buflens[1] <
- sizeof(uuid_t) * lov->desc.ld_tgt_count) {
- CERROR("invalid uuid array returned\n");
- GOTO(out, rc = -EINVAL);
- }
-
- lov->bufsize = sizeof(struct lov_tgt_desc) * lov->desc.ld_tgt_count;
- OBD_ALLOC(lov->tgts, lov->bufsize);
- if (!lov->tgts) {
- CERROR("Out of memory\n");
- GOTO(out, rc = -ENOMEM);
- }
-
- uuidarray = lustre_msg_buf(req->rq_repmsg, 1);
- for (i = 0 ; i < lov->desc.ld_tgt_count; i++)
- memcpy(lov->tgts[i].uuid, uuidarray[i], sizeof(uuid_t));
-
- for (i = 0 ; i < lov->desc.ld_tgt_count; i++) {
- struct obd_device *tgt = class_uuid2obd(uuidarray[i]);
- if (!tgt) {
- CERROR("Target %s not attached\n", uuidarray[i]);
- GOTO(out_mem, rc = -EINVAL);
- }
- if (!(tgt->obd_flags & OBD_SET_UP)) {
- CERROR("Target %s not set up\n", uuidarray[i]);
- GOTO(out_mem, rc = -EINVAL);
- }
- rc = obd_connect(&lov->tgts[i].conn, tgt, NULL);
- if (rc) {
- CERROR("Target %s connect error %d\n",
- uuidarray[i], rc);
- GOTO(out_mem, rc);
- }
- }
-
- out_mem:
- if (rc) {
- for (i = 0 ; i < lov->desc.ld_tgt_count; i++) {
- rc2 = obd_disconnect(&lov->tgts[i].conn);
- if (rc2)
- CERROR("BAD: Target %s disconnect error %d\n",
- uuidarray[i], rc2);
- }
- OBD_FREE(lov->tgts, lov->bufsize);
- }
- out:
- if (rc)
- class_disconnect(conn);
- ptlrpc_free_req(req);
- return rc;
-}
-
-static int lov_disconnect(struct lustre_handle *conn)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct lov_obd *lov = &obd->u.lov;
- int rc;
- int i;
-
- if (!lov->tgts)
- goto out_local;
-
- for (i = 0 ; i < lov->desc.ld_tgt_count; i++) {
- rc = obd_disconnect(&lov->tgts[i].conn);
- if (rc) {
- CERROR("Target %s disconnect error %d\n",
- lov->tgts[i].uuid, rc);
- RETURN(rc);
- }
- }
- OBD_FREE(lov->tgts, lov->bufsize);
- lov->bufsize = 0;
- lov->tgts = NULL;
-
- out_local:
- rc = class_disconnect(conn);
- if (!rc)
- MOD_DEC_USE_COUNT;
- 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("osc setup requires an MDC UUID\n");
- RETURN(-EINVAL);
- }
-
- if (data->ioc_inllen1 > 37) {
- CERROR("mdc UUID must be less than 38 characters\n");
- RETURN(-EINVAL);
- }
-
- 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 inline int lov_stripe_md_size(struct obd_device *obd)
-{
- struct lov_obd *lov = &obd->u.lov;
- int size;
-
- size = sizeof(struct lov_stripe_md) +
- lov->desc.ld_tgt_count * sizeof(struct lov_object_id);
- return size;
-}
-
-/* the LOV counts on oa->o_id to be set as the LOV object id */
-static int lov_create(struct lustre_handle *conn, struct obdo *oa, struct lov_stripe_md **ea)
-{
- int rc = 0, i;
- struct obdo tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct lov_stripe_md *md;
- ENTRY;
-
- if (!ea) {
- CERROR("lov_create needs EA for striping information\n");
- RETURN(-EINVAL);
- }
- if (!export)
- RETURN(-EINVAL);
- lov = &export->exp_obd->u.lov;
-
- oa->o_easize = lov_stripe_md_size(export->exp_obd);
- if (!*ea) {
- OBD_ALLOC(*ea, oa->o_easize);
- if (! *ea)
- RETURN(-ENOMEM);
- }
-
- md = *ea;
- md->lmd_easize = oa->o_easize;
- md->lmd_object_id = oa->o_id;
- if (!md->lmd_stripe_count) {
- md->lmd_stripe_count = lov->desc.ld_default_stripe_count;
- }
-
- if (!md->lmd_stripe_size)
- md->lmd_stripe_size = lov->desc.ld_default_stripe_size;
-
-
-
- for (i = 0; i < md->lmd_stripe_count; i++) {
- struct lov_stripe_md obj_md;
- struct lov_stripe_md *obj_mdp = &obj_md;
- /* create data objects with "parent" OA */
- memcpy(&tmp, oa, sizeof(tmp));
- tmp.o_easize = sizeof(struct lov_stripe_md);
- rc = obd_create(&lov->tgts[i].conn, &tmp, &obj_mdp);
- if (rc)
- GOTO(out_cleanup, rc);
- md->lmd_objects[i].l_object_id = tmp.o_id;
- }
-
- out_cleanup:
- if (rc) {
- int i2, rc2;
- for (i2 = 0 ; i2 < i ; i2++) {
- /* destroy already created objects here */
- tmp.o_id = md->lmd_objects[i].l_object_id;
- rc2 = obd_destroy(&lov->tgts[i].conn, &tmp, NULL);
- if (rc2) {
- CERROR("Failed to remove object from target %d\n",
- i2);
- }
- }
- }
- return rc;
-}
-
-static int lov_destroy(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- int rc = 0, i;
- struct obdo tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- ENTRY;
-
- if (!md) {
- CERROR("LOV requires striping ea for desctruction\n");
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- lov = &export->exp_obd->u.lov;
- for (i = 0; i < md->lmd_stripe_count; i++) {
- /* create data objects with "parent" OA */
- memcpy(&tmp, oa, sizeof(tmp));
- tmp.o_id = md->lmd_objects[i].l_object_id;
- rc = obd_destroy(&lov->tgts[i].conn, &tmp, NULL);
- if (!rc) {
- CERROR("Error destroying object %Ld on %d\n",
- oa->o_id, i);
- }
- }
- RETURN(rc);
-}
-
-static int lov_getattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- int rc = 0, i;
- struct obdo tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- ENTRY;
-
- if (!md) {
- CERROR("LOV requires striping ea for desctruction\n");
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- lov = &export->exp_obd->u.lov;
- for (i = 0; i < md->lmd_stripe_count; i++) {
- /* create data objects with "parent" OA */
- memcpy(&tmp, oa, sizeof(tmp));
- oa->o_id = md->lmd_objects[i].l_object_id;
-
- rc = obd_getattr(&lov->tgts[i].conn, &tmp, NULL);
- if (!rc) {
- CERROR("Error getattr object %Ld on %d\n",
- oa->o_id, i);
- }
- /* XXX can do something more sophisticated here... */
- if (i == 0 ) {
- obd_id id = oa->o_id;
- memcpy(oa, &tmp, sizeof(tmp));
- oa->o_id = id;
- }
- }
- RETURN(rc);
-}
-
-static int lov_setattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- int rc = 0, i;
- struct obdo tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- ENTRY;
-
- if (!md) {
- CERROR("LOV requires striping ea for desctruction\n");
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- lov = &export->exp_obd->u.lov;
- for (i = 0; i < md->lmd_stripe_count; i++) {
- /* create data objects with "parent" OA */
- memcpy(&tmp, oa, sizeof(tmp));
- oa->o_id = md->lmd_objects[i].l_object_id;
-
- rc = obd_setattr(&lov->tgts[i].conn, &tmp, NULL);
- if (!rc) {
- CERROR("Error setattr object %Ld on %d\n",
- oa->o_id, i);
- }
- }
- RETURN(rc);
-}
-
-static int lov_open(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- int rc = 0, i;
- struct obdo tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- ENTRY;
-
- if (!md) {
- CERROR("LOV requires striping ea for opening\n");
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- lov = &export->exp_obd->u.lov;
- for (i = 0; i < md->lmd_stripe_count; i++) {
- /* create data objects with "parent" OA */
- memcpy(&tmp, oa, sizeof(tmp));
- oa->o_id = md->lmd_objects[i].l_object_id;
-
- rc = obd_open(&lov->tgts[i].conn, &tmp, NULL);
- if (rc) {
- CERROR("Error getattr object %Ld on %d\n",
- oa->o_id, i);
- }
- }
- RETURN(rc);
-}
-
-
-static int lov_close(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- int rc = 0, i;
- struct obdo tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- ENTRY;
-
- if (!md) {
- CERROR("LOV requires striping ea for desctruction\n");
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- lov = &export->exp_obd->u.lov;
- for (i = 0; i < md->lmd_stripe_count; i++) {
- /* create data objects with "parent" OA */
- memcpy(&tmp, oa, sizeof(tmp));
- oa->o_id = md->lmd_objects[i].l_object_id;
-
- rc = obd_close(&lov->tgts[i].conn, &tmp, NULL);
- if (!rc) {
- CERROR("Error getattr object %Ld on %d\n",
- oa->o_id, i);
- }
- }
- RETURN(rc);
-}
-
-#ifndef log2
-#define log2(n) ffz(~(n))
-#endif
-
-/* compute offset in stripe i corresponds to offset "in" */
-__u64 lov_offset(struct lov_stripe_md *md, __u64 in, int i)
-{
- __u32 ssz = md->lmd_stripe_size;
- /* full stripes across all * stripe size */
- __u32 out = ( ((__u32)in) / (md->lmd_stripe_count * ssz)) * ssz;
- __u32 off = (__u32)in % (md->lmd_stripe_count * ssz);
-
- if ( in == 0xffffffffffffffff ) {
- return 0xffffffffffffffff;
- }
-
- if ( (i+1) * ssz < off )
- out += ssz;
- else if ( i * ssz > off )
- out += 0;
- else
- out += (off - (i * ssz)) % ssz;
-
- return (__u64) out;
-}
-
-/* compute offset in stripe i corresponds to offset "in" */
-__u64 lov_stripe(struct lov_stripe_md *md, __u64 in, int *j)
-{
- __u32 ssz = md->lmd_stripe_size;
- __u32 off, out;
- /* full stripes across all * stripe size */
- *j = (((__u32) in)/ssz) % md->lmd_stripe_count;
- off = (__u32)in % (md->lmd_stripe_count * ssz);
- out = ( ((__u32)in) / (md->lmd_stripe_count * ssz)) * ssz +
- (off - ((*j) * ssz)) % ssz;;
-
- return (__u64) out;
-}
-
-int lov_stripe_which(struct lov_stripe_md *md, __u64 in)
-{
- __u32 ssz = md->lmd_stripe_size;
- int j;
- j = (((__u32) in)/ssz) % md->lmd_stripe_count;
- return j;
-}
-
-
-/* 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 *md,
- obd_off start, obd_off end)
-{
- int rc = 0, i;
- struct obdo tmp;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- ENTRY;
-
- if (!md) {
- CERROR("LOV requires striping ea for desctruction\n");
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- lov = &export->exp_obd->u.lov;
- for (i = 0; i < md->lmd_stripe_count; i++) {
- __u64 starti = lov_offset(md, start, i);
- __u64 endi = lov_offset(md, end, i);
-
- if (starti == endi)
- continue;
- /* create data objects with "parent" OA */
- memcpy(&tmp, oa, sizeof(tmp));
- oa->o_id = md->lmd_objects[i].l_object_id;
-
- rc = obd_punch(&lov->tgts[i].conn, &tmp, NULL,
- starti, endi);
- if (!rc) {
- CERROR("Error punch object %Ld on %d\n",
- oa->o_id, i);
- }
- }
- RETURN(rc);
-}
-
-struct lov_callback_data {
- struct io_cb_data cbd;
- brw_callback_t cb;
-};
-
-int lov_osc_brw_callback(struct io_cb_data *data, int err, int phase)
-{
- struct lov_callback_data *lovcbd = (struct lov_callback_data *)data;
- int ret = 0;
- ENTRY;
-
- if (phase == CB_PHASE_START)
- RETURN(0);
-
- if (phase == CB_PHASE_FINISH) {
- if (err)
- lovcbd->cbd.err = err;
- if (atomic_dec_and_test(&lovcbd->cbd.refcount))
- ret = lovcbd->cb(&lovcbd->cbd, 0, lovcbd->cbd.err);
- RETURN(ret);
- }
-
- LBUG();
- return 0;
-}
-
-static inline int lov_brw(int cmd, struct lustre_handle *conn,
- struct lov_stripe_md *md,
- obd_count oa_bufs,
- struct brw_page *pga,
- brw_callback_t callback, struct io_cb_data *data)
-{
- int stripe_count = md->lmd_stripe_count;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- struct {
- int bufct;
- int index;
- int subcount;
- struct lov_stripe_md md;
- } *stripeinfo;
- struct brw_page *ioarr;
- int rc, i;
- struct lov_callback_data *lov_cb_data;
- ENTRY;
-
- lov = &export->exp_obd->u.lov;
-
- OBD_ALLOC(lov_cb_data, sizeof(*lov_cb_data));
- if (!lov_cb_data)
- RETURN(-ENOMEM);
-
- OBD_ALLOC(stripeinfo, stripe_count * sizeof(*stripeinfo));
- if (!stripeinfo)
- RETURN(-ENOMEM);
-
- OBD_ALLOC(ioarr, sizeof(*ioarr) * oa_bufs);
- if (!ioarr) {
- OBD_FREE(stripeinfo, stripe_count * sizeof(*stripeinfo));
- RETURN(-ENOMEM);
- }
-
- for (i=0 ; i < oa_bufs ; i++ ) {
- int which;
- which = lov_stripe_which(md, pga[i].pg->index * PAGE_SIZE);
- stripeinfo[which].bufct++;
- }
-
- for (i=0 ; i < stripe_count ; i++) {
- if (i>0)
- stripeinfo[i].index =
- stripeinfo[i-1].index + stripeinfo[i-1].bufct;
- stripeinfo[i].md.lmd_object_id =
- md->lmd_objects[i].l_object_id;
- }
-
- for (i=0 ; i < oa_bufs ; i++ ) {
- int which, shift;
- which = lov_stripe_which(md, pga[i].pg->index * PAGE_SIZE);
-
- shift = stripeinfo[which].index;
- ioarr[shift + stripeinfo[which].subcount] = pga[i];
- pga[i].off = lov_offset(md, pga[i].pg->index * PAGE_SIZE, which);
- stripeinfo[which].subcount++;
- }
-
- lov_cb_data->cbd = *data;
- lov_cb_data->cb = callback;
- atomic_set(&lov_cb_data->cbd.refcount, oa_bufs);
- for (i=0 ; i < stripe_count ; i++) {
- int shift = stripeinfo[i].index;
-
- obd_brw(cmd, &lov->tgts[i].conn, &stripeinfo[i].md,
- stripeinfo[i].bufct, &ioarr[shift],
- lov_osc_brw_callback, (struct io_cb_data *)lov_cb_data);
- }
-
- rc = callback((struct io_cb_data *)lov_cb_data, 0, CB_PHASE_START);
-
- RETURN(rc);
-}
-
-static int lov_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 *lockhs)
-{
- int rc = 0, i;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- ENTRY;
-
- if (!md) {
- CERROR("LOV requires striping ea for desctruction\n");
- RETURN(-EINVAL);
- }
-
- if (!export || !export->exp_obd)
- RETURN(-ENODEV);
-
- lov = &export->exp_obd->u.lov;
- for (i = 0; i < md->lmd_stripe_count; i++) {
- struct ldlm_extent *extent = (struct ldlm_extent *)cookie;
- struct ldlm_extent sub_ext;
- struct lov_stripe_md submd;
-
- sub_ext.start = lov_offset(md, extent->start, i);
- sub_ext.end = lov_offset(md, extent->end, i);
- if ( sub_ext.start == sub_ext.end )
- continue;
-
- submd.lmd_object_id = md->lmd_objects[i].l_object_id;
- submd.lmd_easize = sizeof(submd);
- rc = obd_enqueue(&(lov->tgts[i].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) {
- CERROR("Error punch object %Ld subobj %Ld\n", md->lmd_object_id,
- md->lmd_objects[i].l_object_id);
- }
- }
- RETURN(rc);
-}
-
-static int lov_cancel(struct lustre_handle *conn, struct lov_stripe_md *md, __u32 mode,
- struct lustre_handle *lockhs)
-{
- int rc = 0, i;
- struct obd_export *export = class_conn2export(conn);
- struct lov_obd *lov;
- ENTRY;
-
- if (!md) {
- 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; i < md->lmd_stripe_count; i++) {
- struct lov_stripe_md submd;
-
- if ( lockhs[i].addr == 0 )
- continue;
-
- submd.lmd_object_id = md->lmd_objects[i].l_object_id;
- submd.lmd_easize = sizeof(submd);
- rc = obd_cancel(&lov->tgts[i].conn, &submd, mode, &lockhs[i]);
- if (!rc) {
- CERROR("Error punch object %Ld subobj %Ld\n", md->lmd_object_id,
- md->lmd_objects[i].l_object_id);
- }
- }
- RETURN(rc);
-}
-
-
-
-
-struct obd_ops lov_obd_ops = {
- o_setup: lov_setup,
- o_connect: lov_connect,
- o_disconnect: lov_disconnect,
- 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
-};
-
-
-#define LOV_VERSION "v0.1"
-
-static int __init lov_init(void)
-{
- printk(KERN_INFO "Lustre Logical Object Volume driver " LOV_VERSION
- ", info@clusterfs.com\n");
- return class_register_type(&lov_obd_ops, OBD_LOV_DEVICENAME);
-}
-
-static void __exit lov_exit(void)
-{
- class_unregister_type(OBD_LOV_DEVICENAME);
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Logical Object Volume OBD driver v0.1");
-MODULE_LICENSE("GPL");
-
-module_init(lov_init);
-module_exit(lov_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 = mdc
-modulefs_DATA = mdc.o
-EXTRA_PROGRAMS = mdc
-
-LINX=l_net.c mds_updates.c ll_pack.c lov_pack.c
-mdc_SOURCES = mdc_request.c mdc_reint.c $(LINX)
-lov_pack.c:
- test -e lov_pack.c || ln -sf $(top_srcdir)/lib/lov_pack.c .
-
-ll_pack.c:
- test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c .
-
-l_net.c:
- test -e l_net.c || ln -sf $(top_srcdir)/lib/l_net.c .
-
-mds_updates.c:
- test -e mds_updates.c || ln -sf $(top_srcdir)/lib/mds_updates.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.
- *
- */
-
-#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);
- rc = ptlrpc_check_status(request, rc);
-
- if (rc)
- CERROR("error in handling %d\n", rc);
-
- 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_req2(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 char *tgt, int tgtlen, int mode, __u32 uid,
- __u32 gid, __u64 time, __u64 rdev, struct lov_stripe_md *smd,
- struct ptlrpc_request **request)
-{
- struct mds_rec_create *rec;
- struct ptlrpc_request *req;
- int rc, size[3] = {sizeof(struct mds_rec_create), namelen + 1, 0};
- char *tmp, *bufs[3] = {NULL, NULL, NULL};
- int level, bufcount = 2;
- ENTRY;
-
- if (S_ISREG(mode)) {
- if (!smd) {
- CERROR("File create, but no md (%ld, %*s)\n",
- dir->i_ino, namelen, name);
- LBUG();
- }
- size[2] = smd->lmd_easize;
- bufs[2] = (char *)smd;
- bufcount = 3;
- } else if (S_ISLNK(mode)) {
- size[2] = tgtlen + 1;
- bufcount = 3;
- }
-
- req = ptlrpc_prep_req2(conn, MDS_REINT, bufcount, size, bufs);
- if (!req)
- RETURN(-ENOMEM);
-
- /* mds_create_pack fills bufs[1] with name */
- rec = lustre_msg_buf(req->rq_reqmsg, 0);
- mds_create_pack(req, 0, dir, mode, rdev, uid, gid, time,
- name, namelen, NULL, 0);
-
- if (S_ISREG(mode)) {
- tmp = lustre_msg_buf(req->rq_reqmsg, 2);
- memcpy(tmp, smd, smd->lmd_easize);
- } else if (S_ISLNK(mode)) {
- tmp = lustre_msg_buf(req->rq_reqmsg, 2);
- LOGL0(tgt, tgtlen, tmp);
- }
-
- size[0] = sizeof(struct mds_body);
- req->rq_replen = lustre_msg_size(1, size);
-
- level = LUSTRE_CONN_FULL;
- resend:
- rc = mdc_reint(req, level);
- if (rc == -ERESTARTSYS) {
- __u32 *opcode = lustre_msg_buf(req->rq_reqmsg, 0);
- level = LUSTRE_CONN_RECOVD;
- CERROR("Lost reply: re-create rep.\n");
- req->rq_flags = 0;
- *opcode = NTOH__u32(REINT_RECREATE);
- goto resend;
- }
-
- *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_req2(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_req2(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_req2(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/obd_lov.h>
-
-#define REQUEST_MINOR 244
-
-extern int mds_queue_req(struct ptlrpc_request *);
-
-int mdc_con2cl(struct lustre_handle *conn, struct ptlrpc_client **cl,
- struct ptlrpc_connection **connection,
- struct lustre_handle **rconn)
-{
- struct obd_export *export;
- struct client_obd *mdc;
-
- export = class_conn2export(conn);
- if (!export)
- return -ENOTCONN;
-
- mdc = &export->exp_obd->u.cli;
-
- *cl = mdc->cl_client;
- *connection = mdc->cl_conn;
- *rconn = &export->exp_rconnh;
-
- return 0;
-}
-
-int mdc_getstatus(struct lustre_handle *conn, struct ll_fid *rootfid,
- __u64 *last_committed, __u32 *last_xid,
- struct ptlrpc_request **request)
-{
- struct ptlrpc_request *req;
- struct mds_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- req = ptlrpc_prep_req2(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);
- rc = ptlrpc_check_status(req, rc);
-
- if (!rc) {
- body = lustre_msg_buf(req->rq_repmsg, 0);
- mds_unpack_body(body);
- memcpy(rootfid, &body->fid1, sizeof(*rootfid));
- *last_committed = req->rq_repmsg->last_committed;
- *last_xid = req->rq_repmsg->last_xid;
-
- CDEBUG(D_NET, "root ino=%ld, last_committed=%Lu, last_xid=%d\n",
- (unsigned long)rootfid->id,
- (unsigned long long)*last_committed, *last_xid);
- }
-
- EXIT;
- out:
- ptlrpc_free_req(req);
- return rc;
-}
-
-int mdc_getlovinfo(struct obd_device *obd, struct lustre_handle *mdc_connh,
- uuid_t **uuids, struct ptlrpc_request **request)
-{
- struct ptlrpc_request *req;
- struct mds_status_req *streq;
- struct lov_obd *lov = &obd->u.lov;
- struct client_obd *mdc = &lov->mdcobd->u.cli;
- struct lov_desc *desc = &lov->desc;
- int rc, size[2] = {sizeof(*streq)};
- ENTRY;
-
- req = ptlrpc_prep_req2(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(8000);
-
- /* prepare for reply */
- req->rq_level = LUSTRE_CONN_CON;
- size[0] = sizeof(*desc);
- size[1] = 8000;
- req->rq_replen = lustre_msg_size(2, size);
-
- rc = ptlrpc_queue_wait(req);
- rc = ptlrpc_check_status(req, rc);
-
- if (!rc) {
- memcpy(desc, lustre_msg_buf(req->rq_repmsg, 0), sizeof(*desc));
- *uuids = lustre_msg_buf(req->rq_repmsg, 1);
- lov_unpackdesc(desc);
- }
- mdc->cl_max_mdsize = sizeof(*desc) +
- desc->ld_tgt_count * sizeof(uuid_t);
-
- EXIT;
- 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;
-
- req = ptlrpc_prep_req2(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 (S_ISREG(type)) {
- struct client_obd *mdc = &class_conn2obd(conn)->u.cli;
- bufcount = 2;
- size[1] = mdc->cl_max_mdsize;
- } else if (valid & OBD_MD_LINKNAME) {
- bufcount = 2;
- size[1] = ea_size;
- }
- req->rq_replen = lustre_msg_size(bufcount, size);
-
- rc = ptlrpc_queue_wait(req);
- rc = ptlrpc_check_status(req, rc);
-
- 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;
-}
-
-static int mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
- void *data, __u32 data_len)
-{
- int rc;
- struct inode *inode = data;
- struct lustre_handle lockh;
- ENTRY;
-
- if (data_len != sizeof(*inode)) {
- CERROR("data_len should be %d, but is %d\n", sizeof(*inode),
- data_len);
- LBUG();
- RETURN(-EINVAL);
- }
-
- /* FIXME: do something better than throwing away everything */
- if (inode == NULL)
- LBUG();
- if (S_ISDIR(inode->i_mode)) {
- CDEBUG(D_INODE, "invalidating inode %ld\n", inode->i_ino);
- invalidate_inode_pages(inode);
- }
-
- ldlm_lock2handle(lock, &lockh);
- rc = ldlm_cli_cancel(&lockh);
- if (rc < 0) {
- CERROR("ldlm_cli_cancel: %d\n", rc);
- LBUG();
- }
- RETURN(0);
-}
-
-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, __u64 id,
- 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};
- int size[5] = {sizeof(struct ldlm_request), sizeof(struct ldlm_intent)};
- int rc, flags;
- int repsize[3] = {sizeof(struct ldlm_reply),
- sizeof(struct mds_body),
- obddev->u.cli.cl_max_mdsize};
- struct ldlm_reply *dlm_rep;
- struct ldlm_intent *lit;
- ENTRY;
-
- LDLM_DEBUG_NOLOCK("mdsintent %s dir %ld", ldlm_it2str(it->it_op), dir->i_ino);
-
- switch (it->it_op) {
- case IT_MKDIR:
- it->it_mode = (it->it_mode | S_IFDIR) & ~current->fs->umask;
- break;
- case (IT_CREAT|IT_OPEN):
- case IT_CREAT:
- it->it_mode |= S_IFREG; /* no break */
- case IT_MKNOD:
- it->it_mode &= ~current->fs->umask;
- break;
- case IT_SYMLINK:
- it->it_mode = (it->it_mode | S_IFLNK) & ~current->fs->umask;
- break;
- }
-
- if (it->it_op & (IT_MKDIR | IT_CREAT | IT_SYMLINK | IT_MKNOD)) {
- size[2] = sizeof(struct mds_rec_create);
- size[3] = de->d_name.len + 1;
- size[4] = tgtlen + 1;
- req = ptlrpc_prep_req2(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, id, 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_req2(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(1, 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_req2(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->it_op == IT_RENAME ||
- it->it_op == IT_OPEN || it->it_op == IT_SETATTR ||
- it->it_op == IT_LOOKUP || it->it_op == IT_READLINK) {
- size[2] = sizeof(struct mds_body);
- size[3] = de->d_name.len + 1;
-
- req = ptlrpc_prep_req2(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_req2(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);
- }
-#warning FIXME: the data here needs to be different if a lock was granted for a different inode
- 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 (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);
- }
-
- 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_open(struct lustre_handle *conn, obd_id ino, int type, int flags,
- struct lov_stripe_md *smd, __u64 cookie, __u64 *fh,
- struct ptlrpc_request **request)
-{
- struct ptlrpc_client *cl;
- struct ptlrpc_connection *connection;
- struct lustre_handle *rconn;
- struct mds_body *body;
- int rc, size[2] = {sizeof(*body)}, bufcount = 1;
- struct ptlrpc_request *req;
- ENTRY;
-
- if (smd != NULL) {
- bufcount = 2;
- size[1] = smd->lmd_easize;
- }
-
- mdc_con2cl(conn, &cl, &connection, &rconn);
- req = ptlrpc_prep_req2(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);
- body->extra = cookie;
-
- if (smd != NULL)
- memcpy(lustre_msg_buf(req->rq_reqmsg, 1), smd, smd->lmd_easize);
-
- req->rq_replen = lustre_msg_size(1, size);
-
- rc = ptlrpc_queue_wait(req);
- rc = ptlrpc_check_status(req, rc);
- if (!rc) {
- body = lustre_msg_buf(req->rq_repmsg, 0);
- mds_unpack_body(body);
- *fh = body->extra;
- }
-
- EXIT;
- out:
- *request = req;
- return rc;
-}
-
-int mdc_close(struct lustre_handle *conn,
- obd_id ino, int type, __u64 fh, struct ptlrpc_request **request)
-{
- struct mds_body *body;
- int rc, size = sizeof(*body);
- struct ptlrpc_request *req;
-
- req = ptlrpc_prep_req2(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);
- body->extra = fh;
-
- req->rq_replen = lustre_msg_size(0, NULL);
-
- rc = ptlrpc_queue_wait(req);
- rc = ptlrpc_check_status(req, rc);
-
- 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_conn;
- 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_req2(conn, MDS_READPAGE, 1, &size, NULL);
- if (!req)
- GOTO(out2, rc = -ENOMEM);
-
- bulk = ptlrpc_prep_bulk_page(desc);
- bulk->b_buflen = PAGE_SIZE;
- bulk->b_buf = addr;
- bulk->b_xid = req->rq_xid;
- desc->b_portal = MDS_BULK_PORTAL;
-
- rc = ptlrpc_register_bulk(desc);
- if (rc) {
- CERROR("couldn't setup bulk sink: error %d.\n", rc);
- GOTO(out2, rc);
- }
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- body->fid1.id = ino;
- body->fid1.f_type = type;
- body->size = offset;
-
- req->rq_replen = lustre_msg_size(1, &size);
- rc = ptlrpc_queue_wait(req);
- rc = ptlrpc_check_status(req, rc);
- 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;
-}
-
-int mdc_statfs(struct lustre_handle *conn, struct statfs *sfs,
- struct ptlrpc_request **request)
-{
- struct obd_statfs *osfs;
- struct ptlrpc_request *req;
- int rc, size = sizeof(*osfs);
- ENTRY;
-
- req = ptlrpc_prep_req2(conn, MDS_STATFS, 0, NULL, NULL);
- if (!req)
- GOTO(out, rc = -ENOMEM);
- req->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(req);
- rc = ptlrpc_check_status(req, rc);
-
- if (rc)
- GOTO(out, rc);
-
- osfs = lustre_msg_buf(req->rq_repmsg, 0);
- obd_statfs_unpack(osfs, sfs);
-
- EXIT;
-out:
- *request = req;
-
- return rc;
-}
-
-struct obd_ops mdc_obd_ops = {
- o_setup: client_obd_setup,
- o_cleanup: client_obd_cleanup,
- o_connect: client_obd_connect,
- o_disconnect: client_obd_disconnect,
-};
-
-static int __init ptlrpc_request_init(void)
-{
- return class_register_type(&mdc_obd_ops, 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(mdc_getstatus);
-EXPORT_SYMBOL(mdc_getlovinfo);
-EXPORT_SYMBOL(mdc_enqueue);
-EXPORT_SYMBOL(mdc_getattr);
-EXPORT_SYMBOL(mdc_statfs);
-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);
-
-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=
-
-MODULE = mds
-modulefs_DATA = mds.o mds_extN.o # mds_ext2.o mds_ext3.o
-EXTRA_PROGRAMS = mds mds_extN # mds_ext2 mds_ext3
-
-LINX= mds_updates.c simple.c ll_pack.c l_net.c lov_pack.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
-l_net.c:
- test -e l_net.c || ln -sf $(top_srcdir)/lib/l_net.c
-lov_pack.c:
- test -e lov_pack.c || ln -sf $(top_srcdir)/lib/lov_pack.c
-
-mds_SOURCES = mds_lov.c handler.c mds_reint.c mds_fs.c $(LINX)
-
-
-include $(top_srcdir)/Rules
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * linux/mds/handler.c
- *
- * Lustre Metadata Server (mds) request handler
- *
- * 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> &
- * Andreas Dilger <braam@clusterfs.com>
- *
- */
-
-#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>
-
-extern int mds_get_lovtgts(struct obd_device *obd, int tgt_count,
- uuid_t *uuidarray);
-extern int mds_get_lovdesc(struct obd_device *obd, struct lov_desc *desc);
-extern int mds_update_last_rcvd(struct mds_obd *mds, void *handle,
- struct ptlrpc_request *req);
-static int mds_cleanup(struct obd_device * obddev);
-
-inline struct mds_obd *mds_req2mds(struct ptlrpc_request *req)
-{
- return &req->rq_export->exp_obd->u.mds;
-}
-
-
-/* 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;
- 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->b_xid = req->rq_xid;
- bulk->b_buf = buf;
- bulk->b_buflen = PAGE_SIZE;
- desc->b_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);
- }
-
- wait_event(desc->b_waitq, ptlrpc_check_bulk_sent(desc));
- if (desc->b_flags & PTL_RPC_FL_INTR)
- GOTO(cleanup_buf, rc = -EINTR);
-
- 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 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, 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;
- 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, rc;
- __u64 res_id[3] = {0};
- ENTRY;
-
- if (IS_ERR(de))
- RETURN(de);
-
- res_id[0] = de->d_inode->i_ino;
- 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);
-}
-
-/* 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);
- LBUG();
- iput(inode);
- RETURN(ERR_PTR(-ESTALE));
- }
-
- /* now to find a dentry. If possible, get a well-connected one */
- if (mnt)
- *mnt = mds->mds_vfsmnt;
- spin_lock(&dcache_lock);
- for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
- result = list_entry(lp,struct dentry, d_alias);
- if (! (result->d_flags & DCACHE_NFSD_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_NFSD_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,
- char *cluuid)
-{
- struct obd_export *exp;
- struct mds_client_data *mcd;
- int rc;
-
- MOD_INC_USE_COUNT;
- if (cluuid) {
- struct list_head *p;
- list_for_each(p, &obd->obd_exports) {
- exp = list_entry(p, struct obd_export, exp_chain);
- mcd = exp->exp_mds_data.med_mcd;
- if (mcd && !memcmp(cluuid, mcd->mcd_uuid,
- sizeof(mcd->mcd_uuid))) {
- CDEBUG(D_INFO,
- "existing export for UUID '%s' at %p\n",
- cluuid, exp);
- LASSERT(exp->exp_obd == obd);
- exp->exp_rconnh.addr = conn->addr;
- exp->exp_rconnh.cookie = conn->cookie;
- conn->addr = (__u64) (unsigned long)exp;
- conn->cookie = exp->exp_cookie;
- CDEBUG(D_IOCTL,"connect: addr %Lx cookie %Lx\n",
- (long long)conn->addr,
- (long long)conn->cookie);
- RETURN(0);
- }
- }
- }
-#warning shaver: we might need a real cluuid here
- rc = class_connect(conn, obd, NULL);
- if (rc)
- GOTO(out_dec, rc);
- exp = class_conn2export(conn);
- LASSERT(exp);
-
- 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));
- exp->exp_mds_data.med_mcd = mcd;
- rc = mds_client_add(&exp->exp_mds_data, -1);
- if (rc)
- GOTO(out_mdc, rc);
-
- return 0;
-
-out_mdc:
- OBD_FREE(mcd, sizeof(*mcd));
-out_export:
- class_disconnect(conn);
-out_dec:
- MOD_DEC_USE_COUNT;
-
- RETURN(rc);
-}
-
-static int mds_disconnect(struct lustre_handle *conn)
-{
- struct obd_export *exp;
- int rc;
-
- exp = class_conn2export(conn);
- if (!exp)
- RETURN(-EINVAL);
-
- rc = mds_client_free(&exp->exp_mds_data);
- if (rc)
- CERROR("error freeing client data: rc = %d\n", rc);
-
- rc = class_disconnect(conn);
- if (!rc)
- MOD_DEC_USE_COUNT;
-
- return rc;
-}
-
-static int mds_getstatus(struct ptlrpc_request *req)
-{
- struct mds_obd *mds = mds_req2mds(req);
- struct mds_body *body;
- struct mds_export_data *med = &req->rq_export->exp_mds_data;
- 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);
- }
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- mds_unpack_body(body);
-
- /* Anything we need to do here with the client's trans no or so? */
- body = lustre_msg_buf(req->rq_repmsg, 0);
- memcpy(&body->fid1, &mds->mds_rootfid, sizeof(body->fid1));
-
- LASSERT(med->med_mcd);
-
- /* mcd_last_xid is is stored in little endian on the disk and
- mds_pack_rep_body converts it to network order */
- req->rq_repmsg->last_xid = le32_to_cpu(med->med_mcd->mcd_last_xid);
- mds_pack_rep_body(req);
- 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(req->rq_obd, desc);
- if (rc != 0 ) {
- CERROR("mds_get_lovdesc error %d", rc);
- req->rq_status = rc;
- RETURN(0);
- }
-
- tgt_count = NTOH__u32(desc->ld_tgt_count);
- if (tgt_count * sizeof(uuid_t) > streq->repbuf) {
- CERROR("too many targets, enlarge client buffers\n");
- req->rq_status = -ENOSPC;
- RETURN(0);
- }
-
- mds->mds_max_mdsize = sizeof(desc) + tgt_count * sizeof(uuid_t);
- rc = mds_get_lovtgts(req->rq_obd, 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)
-{
- struct lustre_handle lockh;
- ENTRY;
-
- ldlm_lock2handle(lock, &lockh);
- if (ldlm_cli_cancel(&lockh) < 0)
- LBUG();
- RETURN(0);
-}
-
-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, lock_mode, rc = 0;
- __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;
-
- push_ctxt(&saved, &mds->mds_ctxt);
- de = mds_fid2dentry(mds, &body->fid1, NULL);
- if (IS_ERR(de)) {
- LBUG();
- GOTO(out_pre_de, rc = -ESTALE);
- }
-
- dir = de->d_inode;
- CDEBUG(D_INODE, "parent ino %ld, name %*s\n", dir->i_ino,namelen,name);
-
- lock_mode = (req->rq_reqmsg->opc == MDS_REINT) ? LCK_CW : LCK_PW;
- res_id[0] = dir->i_ino;
-
- rc = ldlm_lock_match(obd->obd_namespace, res_id, LDLM_PLAIN,
- NULL, 0, lock_mode, &lockh);
- if (rc == 0) {
- LDLM_DEBUG_NOLOCK("enqueue res %Lu", 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);
- LBUG();
- GOTO(out_create_dchild, 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, name, dchild->d_inode->i_ino);
-
- 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)) {
- struct lov_stripe_md *md;
- md = lustre_msg_buf(req->rq_repmsg, offset + 1);
- md->lmd_easize = mds->mds_max_mdsize;
- mds_fs_get_md(mds, inode, md);
- }
- /* now a normal case for intent locking */
- rc = 0;
- } else
- rc = -ENOENT;
-
- 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);
- 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;
- int rc, size[2] = {sizeof(*body)}, bufcount = 1;
- ENTRY;
-
- body = lustre_msg_buf(req->rq_reqmsg, offset);
- push_ctxt(&saved, &mds->mds_ctxt);
- de = mds_fid2dentry(mds, &body->fid1, NULL);
- if (IS_ERR(de)) {
- GOTO(out_pop, rc = -ENOENT);
- }
-
- inode = de->d_inode;
- if (S_ISREG(body->fid1.f_type)) {
- bufcount = 2;
- size[1] = mds->mds_max_mdsize;
- } else if (body->valid & OBD_MD_LINKNAME) {
- bufcount = 2;
- size[1] = inode->i_size;
- }
-
- rc = lustre_pack_msg(bufcount, size, NULL, &req->rq_replen,
- &req->rq_repmsg);
- if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_GETATTR_PACK)) {
- CERROR("mds: out of memory\n");
- GOTO(out, rc);
- }
-
- if (body->valid & OBD_MD_LINKNAME) {
- char *tmp = lustre_msg_buf(req->rq_repmsg, 1);
-
- rc = inode->i_op->readlink(de, tmp, size[1]);
-
- if (rc < 0) {
- CERROR("readlink failed: %d\n", rc);
- GOTO(out, rc);
- }
- }
-
- body = lustre_msg_buf(req->rq_repmsg, 0);
- body->ino = inode->i_ino;
- body->generation = inode->i_generation;
- body->atime = inode->i_atime;
- body->ctime = inode->i_ctime;
- body->mtime = inode->i_mtime;
- body->uid = inode->i_uid;
- body->gid = inode->i_gid;
- body->size = inode->i_size;
- body->mode = inode->i_mode;
- body->nlink = inode->i_nlink;
- body->valid = (OBD_MD_FLID | OBD_MD_FLATIME | OBD_MD_FLCTIME |
- OBD_MD_FLMTIME | OBD_MD_FLSIZE | OBD_MD_FLUID |
- OBD_MD_FLGID | OBD_MD_FLNLINK | OBD_MD_FLGENER |
- OBD_MD_FLMODE);
-
- if (S_ISREG(inode->i_mode)) {
- rc = mds_fs_get_md(mds, inode,
- lustre_msg_buf(req->rq_repmsg, 1));
- if (rc < 0) {
- CERROR("mds_fs_get_md failed: %d\n", rc);
- GOTO(out, rc);
- }
- body->valid |= OBD_MD_FLEASIZE;
- } else if (S_ISLNK(inode->i_mode))
- body->valid |= OBD_MD_LINKNAME;
-
-out:
- l_dput(de);
-out_pop:
- pop_ctxt(&saved);
- req->rq_status = rc;
- RETURN(0);
-}
-
-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 = vfs_statfs(mds->mds_sb, &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);
- obd_statfs_pack(osfs, &sfs);
-
-out:
- req->rq_status = rc;
- RETURN(0);
-}
-
-static int mds_open(struct ptlrpc_request *req)
-{
- struct dentry *de;
- struct mds_body *body;
- struct file *file;
- struct vfsmount *mnt;
- struct mds_obd *mds = mds_req2mds(req);
- struct mds_export_data *med;
- __u32 flags;
- struct list_head *tmp;
- struct mds_file_data *mfd;
- 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_OPEN_PACK)) {
- CERROR("mds: out of memory\n");
- req->rq_status = -ENOMEM;
- RETURN(0);
- }
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
-
- /* was this animal open already? */
- /* XXX we should only check on re-open, or do a refcount... */
- med = &req->rq_export->exp_mds_data;
- list_for_each(tmp, &med->med_open_head) {
- struct mds_file_data *fd;
- fd = list_entry(tmp, struct mds_file_data, mfd_list);
- if (body->extra == fd->mfd_clientfd &&
- body->fid1.id == fd->mfd_file->f_dentry->d_inode->i_ino) {
- CERROR("Re opening %Ld\n", body->fid1.id);
- RETURN(0);
- }
- }
-
- OBD_ALLOC(mfd, sizeof(*mfd));
- 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)) {
- req->rq_status = -ENOENT;
- RETURN(0);
- }
-
- /* check if this inode has seen a delayed object creation */
- if (req->rq_reqmsg->bufcount > 1) {
- void *handle;
- struct lov_stripe_md *md;
- struct inode *inode = de->d_inode;
- int rc;
-
- md = lustre_msg_buf(req->rq_reqmsg, 1);
-
- handle = mds_fs_start(mds, de->d_inode, MDS_FSOP_SETATTR);
- if (!handle) {
- req->rq_status = -ENOMEM;
- RETURN(0);
- }
-
- /* XXX error handling */
- rc = mds_fs_set_md(mds, inode, handle, md);
- if (!rc) {
- struct obd_run_ctxt saved;
- push_ctxt(&saved, &mds->mds_ctxt);
- rc = mds_update_last_rcvd(mds, handle, req);
- pop_ctxt(&saved);
- } else {
- req->rq_status = rc;
- RETURN(0);
- }
- /* FIXME: need to return last_rcvd, last_committed */
-
- /* FIXME: keep rc intact */
- rc = mds_fs_commit(mds, de->d_inode, handle);
- if (rc) {
- req->rq_status = rc;
- RETURN(0);
- }
- }
-
- flags = body->flags;
- file = dentry_open(de, mnt, flags & ~O_DIRECT);
- if (!file || IS_ERR(file)) {
- req->rq_status = -EINVAL;
- OBD_FREE(mfd, sizeof(*mfd));
- RETURN(0);
- }
-
- file->private_data = mfd;
- mfd->mfd_file = file;
- mfd->mfd_clientfd = body->extra;
- list_add(&mfd->mfd_list, &med->med_open_head);
-
- body = lustre_msg_buf(req->rq_repmsg, 0);
- /* FIXME: need to have cookies involved here */
- body->extra = (__u64) (unsigned long)file;
- RETURN(0);
-}
-
-static int mds_close(struct ptlrpc_request *req)
-{
- struct dentry *de;
- struct mds_body *body;
- struct file *file;
- struct mds_obd *mds = mds_req2mds(req);
- struct vfsmount *mnt;
- struct mds_file_data *mfd;
- int rc;
- ENTRY;
-
- rc = lustre_pack_msg(0, NULL, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc || OBD_FAIL_CHECK(OBD_FAIL_MDS_CLOSE_PACK)) {
- CERROR("mds: out of memory\n");
- req->rq_status = -ENOMEM;
- RETURN(0);
- }
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- de = mds_fid2dentry(mds, &body->fid1, &mnt);
- if (IS_ERR(de)) {
- req->rq_status = -ENOENT;
- RETURN(0);
- }
-
- /* FIXME: need to have cookies involved here */
- file = (struct file *)(unsigned long)body->extra;
- if (!file->f_dentry)
- LBUG();
- mfd = (struct mds_file_data *)file->private_data;
- list_del(&mfd->mfd_list);
- OBD_FREE(mfd, sizeof(*mfd));
-
- req->rq_status = filp_close(file, 0);
- l_dput(de);
- mntput(mnt);
-
- 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;
- struct obd_run_ctxt saved;
- 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_READPAGE_PACK)) {
- CERROR("mds: out of memory\n");
- GOTO(out, rc = -ENOMEM);
- }
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- push_ctxt(&saved, &mds->mds_ctxt);
- 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));
-
- /* 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 */
- rc = mds_sendpage(req, file, body->size);
-
- filp_close(file, 0);
-out_pop:
- pop_ctxt(&saved);
-out:
- req->rq_status = rc;
- RETURN(0);
-}
-
-int mds_reint(int offset, struct ptlrpc_request *req)
-{
- 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;
-}
-
-int mds_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_MDS_HANDLE_UNPACK)) {
- CERROR("lustre_mds: Invalid request\n");
- GOTO(out, rc);
- }
-
- if (req->rq_reqmsg->type != PTL_RPC_MSG_REQUEST) {
- CERROR("lustre_mds: wrong packet type sent %d\n",
- req->rq_reqmsg->type);
- GOTO(out, rc = -EINVAL);
- }
-
- if (req->rq_reqmsg->opc != MDS_CONNECT && req->rq_export == NULL)
- GOTO(out, rc = -ENOTCONN);
-
- if (strcmp(req->rq_obd->obd_type->typ_name, "mds") != 0)
- GOTO(out, rc = -EINVAL);
-
- switch (req->rq_reqmsg->opc) {
- case MDS_CONNECT:
- CDEBUG(D_INODE, "connect\n");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_CONNECT_NET, 0);
- rc = target_handle_connect(req);
- break;
-
- case MDS_DISCONNECT:
- CDEBUG(D_INODE, "disconnect\n");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_DISCONNECT_NET, 0);
- rc = target_handle_disconnect(req);
- goto out;
-
- case MDS_GETSTATUS:
- CDEBUG(D_INODE, "getstatus\n");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_GETSTATUS_NET, 0);
- rc = mds_getstatus(req);
- break;
-
- case MDS_GETLOVINFO:
- CDEBUG(D_INODE, "getlovinfo\n");
- rc = mds_getlovinfo(req);
- break;
-
- case MDS_GETATTR:
- CDEBUG(D_INODE, "getattr\n");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_GETATTR_NET, 0);
- rc = mds_getattr(0, req);
- break;
-
- case MDS_STATFS:
- CDEBUG(D_INODE, "statfs\n");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_STATFS_NET, 0);
- rc = mds_statfs(req);
- break;
-
- case MDS_READPAGE:
- CDEBUG(D_INODE, "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);
- CDEBUG(D_INODE, "reint\n");
- 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(0, req);
- OBD_FAIL_RETURN(OBD_FAIL_MDS_REINT_NET_REP, 0);
- break;
- }
-
- case MDS_OPEN:
- CDEBUG(D_INODE, "open\n");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_OPEN_NET, 0);
- rc = mds_open(req);
- break;
-
- case MDS_CLOSE:
- CDEBUG(D_INODE, "close\n");
- OBD_FAIL_RETURN(OBD_FAIL_MDS_CLOSE_NET, 0);
- rc = mds_close(req);
- break;
-
- case LDLM_ENQUEUE:
- CDEBUG(D_INODE, "enqueue\n");
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_ENQUEUE, 0);
- rc = ldlm_handle_enqueue(req);
- if (rc)
- break;
- RETURN(0);
-
- case LDLM_CONVERT:
- CDEBUG(D_INODE, "convert\n");
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_CONVERT, 0);
- rc = ldlm_handle_convert(req);
- if (rc)
- break;
- RETURN(0);
-
- 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);
- case LDLM_BL_CALLBACK:
- case LDLM_CP_CALLBACK:
- CDEBUG(D_INODE, "callback\n");
- 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_obd *mds = mds_req2mds(req);
- req->rq_repmsg->last_xid = HTON__u64(mds->mds_last_rcvd);
- 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:
- /* Still not 100% sure whether we should reply with the server
- * last_rcvd or that of this client. I'm not sure it even makes
- * a difference on a per-client basis, because last_rcvd is global
- * and we are not supposed to allow transactions while in recovery.
- */
- if (rc) {
- CERROR("mds: processing error %d\n", 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.
- */
-static
-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);
- }
- rc = fsync_dev(filp->f_dentry->d_inode->i_rdev);
- if (rc)
- CERROR("error flushing MDS server data: rc = %d\n", rc);
-
- return 0;
-}
-
-/* Do recovery actions for the MDS */
-static int mds_recover(struct obd_device *obddev)
-{
- struct mds_obd *mds = &obddev->u.mds;
- struct obd_run_ctxt saved;
- int rc;
-
- /* This happens at the end when recovery is complete */
- ++mds->mds_mount_count;
- push_ctxt(&saved, &mds->mds_ctxt);
- rc = mds_update_server_data(mds);
- pop_ctxt(&saved);
-
- return rc;
-}
-
-#define MDS_NUM_THREADS 8
-/* mount the file system (secretly) */
-static int mds_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;
- 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);
- }
-
- mds->mds_sb = mnt->mnt_root->d_inode->i_sb;
- if (!mds->mds_sb)
- GOTO(err_put, rc = -ENODEV);
-
- mds->mds_max_mdsize = sizeof(struct lov_stripe_md);
- rc = mds_fs_setup(obddev, mnt);
- if (rc) {
- CERROR("MDS filesystem method init failed: rc = %d\n", rc);
- GOTO(err_put, rc);
- }
-
- mds->mds_service = ptlrpc_init_svc(64 * 1024, MDS_REQUEST_PORTAL,
- MDC_REPLY_PORTAL, "self",mds_handle);
- if (!mds->mds_service) {
- CERROR("failed to start service\n");
- GOTO(err_fs, rc = -EINVAL);
- }
-
- obddev->obd_namespace =
- ldlm_namespace_new("mds_server", LDLM_NAMESPACE_SERVER);
- if (obddev->obd_namespace == NULL) {
- mds_cleanup(obddev);
- GOTO(err_svc, rc = -ENOMEM);
- }
-
- for (i = 0; i < MDS_NUM_THREADS; i++) {
- char name[32];
- sprintf(name, "lustre_MDS_%02d", i);
- rc = ptlrpc_start_thread(obddev, mds->mds_service, name);
- if (rc) {
- CERROR("cannot start MDS thread #%d: rc %d\n", i, rc);
- GOTO(err_thread, rc);
- }
- }
-
- rc = mds_recover(obddev);
- if (rc)
- GOTO(err_thread, rc);
-
- RETURN(0);
-
-err_thread:
- ptlrpc_stop_all_threads(mds->mds_service);
-err_svc:
- ptlrpc_unregister_service(mds->mds_service);
-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;
-
- ptlrpc_stop_all_threads(mds->mds_service);
- ptlrpc_unregister_service(mds->mds_service);
-
- sb = mds->mds_sb;
- if (!mds->mds_sb)
- RETURN(0);
-
- push_ctxt(&saved, &mds->mds_ctxt);
- 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);
-
- 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, 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 bufcount = -1, 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));
-
- /* prepare reply */
- switch((long)it->opc) {
- case IT_GETATTR:
- /* Note that in the negative case you may be returning
- * a file and its obdo */
- case IT_CREAT:
- case IT_CREAT|IT_OPEN:
- case IT_LINK:
- case IT_LOOKUP:
- case IT_MKDIR:
- case IT_MKNOD:
- case IT_OPEN:
- case IT_READLINK:
- case IT_RENAME:
- case IT_RMDIR:
- case IT_SETATTR:
- case IT_SYMLINK:
- case IT_UNLINK:
- bufcount = 3;
- break;
- case IT_RENAME2:
- bufcount = 1;
- break;
- default:
- LBUG();
- }
-
- rc = lustre_pack_msg(bufcount, 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(2, req);
- 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_LINK:
- case IT_MKDIR:
- case IT_MKNOD:
- case IT_RENAME2:
- case IT_RMDIR:
- case IT_SYMLINK:
- case IT_UNLINK:
- rc = mds_reint(2, req);
- 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_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\n");
- LBUG();
- }
-
- if (it->opc == IT_UNLINK || it->opc == IT_RMDIR ||
- it->opc == IT_RENAME || it->opc == IT_RENAME2)
- RETURN(ELDLM_LOCK_ABORTED);
-
- rep->lock_policy_res2 = req->rq_status;
- mds_rep = lustre_msg_buf(req->rq_repmsg, 1);
- new_resid[0] = NTOH__u32(mds_rep->ino);
- if (new_resid[0] == 0)
- LBUG();
- old_res = lock->l_resource->lr_name[0];
-
- CDEBUG(D_INFO, "remote intent: locking %d instead of"
- "%ld\n", mds_rep->ino, (long)old_res);
-
- 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) {
- CERROR("out of memory\n");
- LBUG();
- RETURN(-ENOMEM);
- }
- }
- RETURN(rc);
-}
-
-
-extern int mds_iocontrol(long 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_connect: mds_connect,
- o_disconnect: mds_disconnect,
- o_setup: mds_setup,
- o_cleanup: mds_cleanup,
- o_iocontrol: mds_iocontrol
-};
-
-static int __init mds_init(void)
-{
- class_register_type(&mds_obd_ops, LUSTRE_MDS_NAME);
- ldlm_register_intent(ldlm_intent_policy);
- return 0;
-}
-
-static void __exit mds_exit(void)
-{
- ldlm_unregister_intent();
- class_unregister_type(LUSTRE_MDS_NAME);
-}
-
-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:
- *
- * 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;
-
- /* 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)
- return inode->i_op->setattr(dentry, iattr);
- else
- return inode_setattr(inode, iattr);
-}
-
-/*
- * 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:
- *
- * linux/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 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/jbd.h>
-#include <linux/ext3_fs.h>
-#include <linux/ext3_jbd.h>
-#include <linux/lustre_mds.h>
-#include <linux/module.h>
-
-static struct mds_fs_operations mds_ext3_fs_ops;
-static kmem_cache_t *jcb_cache;
-static int jcb_cache_count;
-
-struct mds_cb_data {
- struct journal_callback cb_jcb;
- struct mds_obd *cb_mds;
- __u64 cb_last_rcvd;
-};
-
-/*
- * 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;
-
- 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_DATA_TRANS_BLOCKS;
- break;
- case MDS_FSOP_SETATTR:
- /* Setattr on inode */
- nblocks += 1;
- break;
- default: CERROR("unknown transaction start op %d\n", op);
- LBUG();
- }
-
- return journal_start(EXT3_JOURNAL(inode), nblocks);
-}
-
-static int mds_ext3_commit(struct inode *inode, void *handle)
-{
- return journal_stop((handle_t *)handle);
-}
-
-static int mds_ext3_setattr(struct dentry *dentry, void *handle,
- struct iattr *iattr)
-{
- struct inode *inode = dentry->d_inode;
-
- /* 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;
-
- /* an _even_more_ horrible hack to make this hack work with
- * ext3. This is because ext3 keeps a separate inode size
- * until the inode is committed to ensure consistency. This
- * will also go away with the move to EAs.
- */
- EXT3_I(inode)->i_disksize = inode->i_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)
- return inode->i_op->setattr(dentry, iattr);
- else
- return inode_setattr(inode, iattr);
-}
-
-/*
- * FIXME: nasty hack - store the object id in the first two
- * direct block spots. This should be done with EAs...
- * Note also that this does not currently mark the inode
- * dirty (it currently is used with other operations that
- * subsequently also mark the inode dirty).
- */
-static int mds_ext3_set_objid(struct inode *inode, void *handle, obd_id id)
-{
- *((__u64 *)EXT3_I(inode)->i_data) = cpu_to_le64(id);
- return 0;
-}
-
-static int mds_ext3_get_objid(struct inode *inode, obd_id *id)
-{
- *id = le64_to_cpu(*((__u64 *)EXT3_I(inode)->i_data));
-
- return 0;
-}
-
-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_objid(inode, handle, 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(void *jcb, int error)
-{
- struct mds_cb_data *mcb = (struct mds_cb_data *)jcb;
-
- CDEBUG(D_EXT2, "got callback for last_rcvd %Ld: 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(jcb_cache, mcb);
- --jcb_cache_count;
-}
-
-#ifdef HAVE_JOURNAL_CALLBACK
-static void mds_ext3_callback_func(void *cb_data)
-{
- mds_ext3_callback_status(cb_data, 0);
-}
-#endif
-
-static int mds_ext3_set_last_rcvd(struct mds_obd *mds, void *handle)
-{
- struct mds_cb_data *mcb;
-
- mcb = kmem_cache_alloc(jcb_cache, GFP_NOFS);
- if (!mcb)
- RETURN(-ENOMEM);
-
- ++jcb_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: %Ld\n",
- (unsigned long long)mcb->cb_last_rcvd);
- journal_callback_set(handle, mds_ext3_callback_status,
- (void *)mcb);
-#elif defined(HAVE_JOURNAL_CALLBACK)
- /* XXX original patch version - remove soon */
-#warning "using old journal callback kernel patch, please update"
- CDEBUG(D_EXT2, "set callback for last_rcvd: %Ld\n",
- (unsigned long long)mcb->cb_last_rcvd);
- journal_callback_set(handle, mds_ext3_callback_func, mcb);
-#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;
-}
-
-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_objid: mds_ext3_set_objid,
- fs_get_objid: mds_ext3_get_objid,
- 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,
-};
-
-static int __init mds_ext3_init(void)
-{
- int rc;
-
- jcb_cache = kmem_cache_create("mds_ext3_jcb",
- sizeof(struct mds_cb_data), 0,
- 0, NULL, NULL);
- if (!jcb_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(jcb_cache);
-out:
- return rc;
-}
-
-static void __exit mds_ext3_exit(void)
-{
- int rc = 0;
-
- mds_unregister_fs_type("ext3");
- rc = kmem_cache_destroy(jcb_cache);
-
- if (rc || jcb_cache_count) {
- CERROR("can't free MDS callback cache: count %d, rc = %d\n",
- jcb_cache_count, rc);
- }
-}
-
-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:
- *
- * linux/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 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/jbd.h>
-#include <linux/extN_fs.h>
-#include <linux/extN_jbd.h>
-#include <linux/extN_xattr.h>
-#include <linux/lustre_mds.h>
-#include <linux/module.h>
-#include <linux/obd_lov.h>
-
-static struct mds_fs_operations mds_extN_fs_ops;
-static kmem_cache_t *jcb_cache;
-static int jcb_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"
-
-#define XATTR_MDS_MO_MAGIC 0x4711
-
-/*
- * 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;
-
- 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();
- }
-
- return journal_start(EXTN_JOURNAL(inode), nblocks);
-}
-
-static int mds_extN_commit(struct inode *inode, void *handle)
-{
- return journal_stop((handle_t *)handle);
-}
-
-static int mds_extN_setattr(struct dentry *dentry, void *handle,
- struct iattr *iattr)
-{
- struct inode *inode = dentry->d_inode;
-
- if (inode->i_op->setattr)
- return inode->i_op->setattr(dentry, iattr);
- else
- return inode_setattr(inode, iattr);
-}
-
-static int mds_extN_set_md(struct inode *inode, void *handle,
- struct lov_stripe_md *md)
-{
- int rc;
-
- lock_kernel();
- down(&inode->i_sem);
- if (md == NULL)
- rc = extN_xattr_set(handle, inode, EXTN_XATTR_INDEX_LUSTRE,
- XATTR_LUSTRE_MDS_OBJID, NULL, 0, 0);
- else {
- md->lmd_magic = cpu_to_le32(XATTR_MDS_MO_MAGIC);
- rc = extN_xattr_set(handle, inode, EXTN_XATTR_INDEX_LUSTRE,
- XATTR_LUSTRE_MDS_OBJID, md,
- md->lmd_easize, XATTR_CREATE);
- }
- up(&inode->i_sem);
- unlock_kernel();
-
- if (rc) {
- CERROR("error adding objectid %Ld to inode %ld: %d\n",
- (unsigned long long)md->lmd_object_id, inode->i_ino, rc);
- LBUG();
- }
- return rc;
-}
-
-static int mds_extN_get_md(struct inode *inode, struct lov_stripe_md *md)
-{
- int rc;
- int size = md->lmd_easize;
-
- lock_kernel();
- down(&inode->i_sem);
- rc = extN_xattr_get(inode, EXTN_XATTR_INDEX_LUSTRE,
- XATTR_LUSTRE_MDS_OBJID, md, size);
-
- up(&inode->i_sem);
- unlock_kernel();
-
- 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(md, 0, size);
- } else if (md->lmd_magic != cpu_to_le32(XATTR_MDS_MO_MAGIC)) {
- CERROR("MDS striping md for ino %ld has bad magic\n",
- inode->i_ino);
- rc = -EINVAL;
- } else {
- /* This field is byteswapped because it appears in the
- * catalogue. All others are opaque to the MDS */
- md->lmd_object_id = le64_to_cpu(md->lmd_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))
- CERROR("error clearing obdo 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(void *jcb, int error)
-{
- struct mds_cb_data *mcb = (struct mds_cb_data *)jcb;
-
- CDEBUG(D_EXT2, "got callback for last_rcvd %Ld: 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(jcb_cache, jcb);
- --jcb_cache_count;
-}
-
-#ifdef HAVE_JOURNAL_CALLBACK
-static void mds_extN_callback_func(void *cb_data)
-{
- mds_extN_callback_status(cb_data, 0);
-}
-#endif
-
-static int mds_extN_set_last_rcvd(struct mds_obd *mds, void *handle)
-{
- struct mds_cb_data *mcb;
-
- mcb = kmem_cache_alloc(jcb_cache, GFP_NOFS);
- if (!mcb)
- RETURN(-ENOMEM);
-
- ++jcb_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: %Ld\n",
- (unsigned long long)mcb->cb_last_rcvd);
- journal_callback_set(handle, mds_extN_callback_status,
- (void *)mcb);
-#elif defined(HAVE_JOURNAL_CALLBACK)
- /* XXX original patch version - remove soon */
-#warning "using old journal callback kernel patch, please update"
- CDEBUG(D_EXT2, "set callback for last_rcvd: %Ld\n",
- (unsigned long long)mcb->cb_last_rcvd);
- journal_callback_set(handle, mds_extN_callback_func, mcb);
-#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();
- jcb_cache = kmem_cache_create("mds_extN_jcb",
- sizeof(struct mds_cb_data), 0,
- 0, NULL, NULL);
- if (!jcb_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(jcb_cache);
-out:
- return rc;
-}
-
-static void __exit mds_extN_exit(void)
-{
- int rc;
-
- mds_unregister_fs_type("extN");
- rc = kmem_cache_destroy(jcb_cache);
-
- if (rc || jcb_cache_count) {
- CERROR("can't free MDS callback cache: count %d, rc = %d\n",
- jcb_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;
-};
-
-#define MDS_MAX_CLIENTS 1024
-#define MDS_MAX_CLIENT_WORDS (MDS_MAX_CLIENTS / sizeof(unsigned long))
-
-static unsigned long last_rcvd_slots[MDS_MAX_CLIENT_WORDS];
-
-/* 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_export_data *med, int cl_off)
-{
- if (cl_off == -1) {
- unsigned long *word;
- int bit;
-
- repeat:
- word = last_rcvd_slots;
- while(*word == ~0UL)
- ++word;
- if (word - last_rcvd_slots >= MDS_MAX_CLIENT_WORDS) {
- CERROR("no room for clients - fix MDS_MAX_CLIENTS\n");
- return -ENOMEM;
- }
- bit = ffz(*word);
- if (test_and_set_bit(bit, word)) {
- CERROR("found bit %d set for word %d - fix locking\n",
- bit, word - last_rcvd_slots);
- LBUG();
- goto repeat;
- }
- cl_off = word - last_rcvd_slots + bit;
- } else {
- if (test_and_set_bit(cl_off, last_rcvd_slots)) {
- CERROR("bit %d already set in bitmap - bad bad\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;
- return 0;
-}
-
-int mds_client_free(struct mds_export_data *med)
-{
- unsigned long *word;
- int bit;
-
- CDEBUG(D_INFO, "freeing client at offset %d with UUID '%s'\n",
- med->med_off, med->med_mcd->mcd_uuid);
-
- word = last_rcvd_slots + med->med_off / sizeof(unsigned long);
- bit = med->med_off % sizeof(unsigned long);
-
- if (!test_and_clear_bit(bit, word)) {
- CERROR("bit %d already clear in word %d - bad bad\n",
- bit, word - last_rcvd_slots);
- LBUG();
- }
-
- 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;
-}
-
-#define LAST_RCVD "last_rcvd"
-
-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 fsize = f->f_dentry->d_inode->i_size;
- loff_t off = 0;
- int cl_off;
- __u64 last_rcvd = 0;
- __u64 last_mount;
- int clients = 0;
- 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, rc = sizeof(*mcd);
- off <= fsize - sizeof(*mcd) && rc == sizeof(*mcd);
- off = MDS_LR_CLIENT + ++cl_off * MDS_LR_SIZE) {
- 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;
- }
-
- last_rcvd = le64_to_cpu(mcd->mcd_last_rcvd);
-
- /* Do client recovery here (open files, etc) */
- if (last_rcvd && (last_mount - le64_to_cpu(mcd->mcd_mount_count)
- < MDS_MOUNT_RECOV)) {
- struct obd_export *export = class_new_export(obddev);
- if (!export) {
- rc = -ENOMEM;
- break;
- }
- export->exp_mds_data.med_mcd = mcd;
- mds_client_add(&export->exp_mds_data, cl_off);
- mcd = NULL;
- clients++;
- } else {
- CDEBUG(D_INFO,
- "ignored client %d, UUID '%s', last_mount %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;
- }
- }
- CDEBUG(D_INODE, "got %Lu for highest last_rcvd value, %d/%d clients\n",
- (unsigned long long)mds->mds_last_rcvd, clients, cl_off);
-
- if (mcd)
- OBD_FREE(mcd, sizeof(*mcd));
-
- /* After recovery, there can be no local uncommitted transactions */
- mds->mds_last_committed = mds->mds_last_rcvd;
-
- 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);
- 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);
-
- 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_lov.h>
-#include <linux/obd_class.h>
-#include <linux/lustre_lib.h>
-
-int mds_configure_lov(struct obd_device *obd, struct lov_desc *desc,
- 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;
-
- tgt_count = desc->ld_tgt_count;
- lov_packdesc(desc);
-
- push_ctxt(&saved, &mds->mds_ctxt);
- 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);
- RETURN(rc);
-}
-
-int mds_get_lovdesc(struct obd_device *obd, struct lov_desc *desc)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct obd_run_ctxt saved;
- struct file *f;
- int rc;
-
- push_ctxt(&saved, &mds->mds_ctxt);
- f = filp_open("LOVDESC", O_RDONLY, 0644);
- if (!f || IS_ERR(f)) {
- CERROR("Cannot open LOVDESC file\n");
- pop_ctxt(&saved);
- RETURN(-EIO);
- }
-
- 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\n");
- pop_ctxt(&saved);
- RETURN(-EIO);
- }
- pop_ctxt(&saved);
-
- RETURN(0);
-}
-
-int mds_get_lovtgts(struct obd_device *obd, int tgt_count, uuid_t *uuidarray)
-{
- struct mds_obd *mds = &obd->u.mds;
- struct obd_run_ctxt saved;
- struct file *f;
- int rc;
- int rc2;
-
- push_ctxt(&saved, &mds->mds_ctxt);
- 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(uuid_t),
- &f->f_pos);
- rc2 = filp_close(f, 0);
- if (rc2)
- CERROR("Error closing LOVTGTS file: rc = %d\n", rc2);
-
- if (rc != tgt_count * sizeof(uuid_t)) {
- 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);
-
- RETURN(rc);
-}
-
-int mds_iocontrol(long 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;
- int count;
- int rc;
-
-
- switch (cmd) {
- case OBD_IOC_LOV_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;
- if (sizeof(uuid_t) * count != data->ioc_inllen2) {
- CERROR("UUID array size wrong\n");
- RETURN(-EINVAL);
- }
- rc = mds_configure_lov(obd, desc, (uuid_t *)data->ioc_inlbuf2);
-
- 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.
- * author: Peter Braam <braam@clusterfs.com>
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- */
-
-// XXX - add transaction sequence numbers
-
-#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);
-
-/* Assumes caller has already pushed us into the kernel context. */
-int mds_update_last_rcvd(struct mds_obd *mds, void *handle,
- struct ptlrpc_request *req)
-{
- struct mds_export_data *med = &req->rq_export->exp_mds_data;
- struct mds_client_data *mcd = med->med_mcd;
- loff_t off;
- int rc;
-
- off = MDS_LR_CLIENT + med->med_off * MDS_LR_SIZE;
-
- ++mds->mds_last_rcvd; /* lock this, or make it an LDLM function? */
- req->rq_repmsg->transno = HTON__u64(mds->mds_last_rcvd);
- mcd->mcd_last_rcvd = cpu_to_le64(mds->mds_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);
- rc = lustre_fwrite(mds->mds_rcvd_filp, (char *)mcd, sizeof(*mcd), &off);
- CDEBUG(D_INODE, "wrote trans #%Ld for client '%s' at #%d: rc = %d\n",
- mds->mds_last_rcvd, mcd->mcd_uuid, med->med_off, rc);
- // store new value and last committed value in req struct
-
- if (rc == sizeof(*mcd))
- rc = 0;
- else {
- CERROR("error writing to last_rcvd file: rc = %d\n", rc);
- if (rc >= 0)
- rc = -EIO;
- }
-
- 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 dentry *de;
- 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)) {
- LBUG();
- GOTO(out_setattr_de, rc = -ESTALE);
- }
- }
- CDEBUG(D_INODE, "ino %ld\n", de->d_inode->i_ino);
-
- OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_SETATTR_WRITE,
- de->d_inode->i_sb->s_dev);
-
- lock_kernel();
- handle = mds_fs_start(mds, de->d_inode, MDS_FSOP_SETATTR);
- if (!handle)
- GOTO(out_unlock, rc = PTR_ERR(handle));
- rc = mds_fs_setattr(mds, de, handle, &rec->ur_iattr);
-
- if (!rc)
- rc = mds_update_last_rcvd(mds, handle, req);
-
- 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_unlock:
- unlock_kernel();
-out_setattr_de:
- l_dput(de);
-out_setattr:
- req->rq_status = rc;
- return (0);
-}
-
-static int mds_reint_recreate(struct mds_update_record *rec, int offset,
- struct ptlrpc_request *req)
-{
- struct dentry *de = NULL;
- struct mds_obd *mds = mds_req2mds(req);
- struct dentry *dchild = NULL;
- struct inode *dir;
- int rc = 0;
- ENTRY;
-
- de = mds_fid2dentry(mds, rec->ur_fid1, NULL);
- if (IS_ERR(de) || OBD_FAIL_CHECK(OBD_FAIL_MDS_REINT_CREATE)) {
- LBUG();
- GOTO(out_create_de, rc = -ESTALE);
- }
- dir = de->d_inode;
- CDEBUG(D_INODE, "parent ino %ld\n", dir->i_ino);
-
- 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));
- up(&dir->i_sem);
- LBUG();
- GOTO(out_create_dchild, rc = -ESTALE);
- }
-
- if (dchild->d_inode) {
- struct mds_body *body;
- rc = 0;
- body = lustre_msg_buf(req->rq_repmsg, 0);
- body->ino = dchild->d_inode->i_ino;
- body->generation = dchild->d_inode->i_generation;
- } else {
- CERROR("child doesn't exist (dir %ld, name %s)\n",
- dir->i_ino, rec->ur_name);
- rc = -ENOENT;
- LBUG();
- }
-
-out_create_dchild:
- l_dput(dchild);
- up(&dir->i_sem);
-out_create_de:
- l_dput(de);
- 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;
-
- if (strcmp(req->rq_export->exp_obd->obd_type->typ_name, "mds") != 0)
- LBUG();
-
- 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;
- struct lov_stripe_md *md;
- CDEBUG(D_INODE, "child exists (dir %ld, name %s, ino %ld)\n",
- dir->i_ino, rec->ur_name, dchild->d_inode->i_ino);
-
- 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)) {
- md = lustre_msg_buf(req->rq_repmsg, offset + 1);
- md->lmd_easize = mds->mds_max_mdsize;
-
- if (mds_fs_get_md(mds, inode, md) < 0)
- memset(md, 0, md->lmd_easize);
- }
- /* now a normal case for intent locking */
- GOTO(out_create_dchild, rc = -EEXIST);
- }
-
- OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_CREATE_WRITE, 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;
- }
-
- switch (type) {
- case S_IFREG:{
- handle = mds_fs_start(mds, dir, MDS_FSOP_CREATE);
- if (!handle)
- GOTO(out_create_dchild, 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 (!handle)
- GOTO(out_create_dchild, 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 (!handle)
- GOTO(out_create_dchild, PTR_ERR(handle));
- rc = vfs_symlink(dir, dchild, rec->ur_tgt);
- 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 (!handle)
- GOTO(out_create_dchild, PTR_ERR(handle));
- rc = vfs_mknod(dir, dchild, rec->ur_mode, rdev);
- EXIT;
- break;
- }
- default:
- CERROR("bad file type %o for create of %s\n", type,
- rec->ur_name);
- GOTO(out_create_dchild, rc = -EINVAL);
- }
-
- if (rc) {
- CERROR("error during create: %d\n", rc);
- if (rc != -ENOSPC)
- LBUG();
- GOTO(out_create_commit, rc);
- } else {
- struct iattr iattr;
- struct inode *inode = dchild->d_inode;
- struct mds_body *body;
-
- CDEBUG(D_INODE, "created ino %ld\n", dchild->d_inode->i_ino);
- if (!offset && type == S_IFREG) {
- struct lov_stripe_md *md;
- md = lustre_msg_buf(req->rq_reqmsg, 2);
- rc = mds_fs_set_md(mds, inode, handle, md);
- if (rc) {
- CERROR("error %d setting LOV MD for %ld\n",
- rc, inode->i_ino);
- GOTO(out_create_unlink, rc);
- }
- }
-
- 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;
-
- 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? */
- }
-
- rc = mds_update_last_rcvd(mds, handle, req);
- if (rc) {
- CERROR("error on update_last_rcvd: rc = %d\n", rc);
- /* XXX should we abort here in case of error? */
- }
-
- body = lustre_msg_buf(req->rq_repmsg, offset);
- body->ino = inode->i_ino;
- body->generation = inode->i_generation;
- body->valid = OBD_MD_FLID | OBD_MD_FLGENER;
- }
- EXIT;
-out_create_commit:
- 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_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);
- }
-
- 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;
- char *name;
- int namelen;
- struct inode *dir, *inode;
- int lock_mode;
- struct lustre_handle lockh, child_lockh;
- void *handle;
- int rc = 0;
- int err;
- ENTRY;
-
- /* a name was supplied by the client; fid1 is the directory */
- lock_mode = (req->rq_reqmsg->opc == MDS_REINT) ? LCK_CW : LCK_PW;
- de = mds_fid2locked_dentry(obd, rec->ur_fid1, NULL, lock_mode, &lockh);
- if (IS_ERR(de)) {
- LBUG();
- RETURN(PTR_ERR(de));
- }
-
- name = lustre_msg_buf(req->rq_reqmsg, offset + 1);
- namelen = req->rq_reqmsg->buflens[offset + 1] - 1;
- dchild = mds_name2locked_dentry(obd, de, NULL, name, namelen,
- LCK_EX, &child_lockh, lock_mode);
-
- if (IS_ERR(dchild) || OBD_FAIL_CHECK(OBD_FAIL_MDS_REINT_UNLINK)) {
- 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) {
- CDEBUG(D_INODE, "child doesn't exist (dir %ld, name %s\n",
- dir->i_ino, rec->ur_name);
- /* XXX should be out_unlink_cancel, or do we keep child_lockh? */
- GOTO(out_unlink_dchild, rc = -ENOENT);
- } else if (offset) {
- struct mds_body *body = lustre_msg_buf(req->rq_repmsg, 1);
- mds_pack_inode2fid(&body->fid1, inode);
- mds_pack_inode2body(body, inode);
- }
-
- OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_UNLINK_WRITE, dir->i_sb->s_dev);
-
- switch (rec->ur_mode) {
- case S_IFDIR:
- handle = mds_fs_start(mds, dir, MDS_FSOP_RMDIR);
- if (!handle)
- GOTO(out_unlink_cancel, rc = PTR_ERR(handle));
- rc = vfs_rmdir(dir, dchild);
- break;
- case S_IFREG:
- if ((inode->i_mode & S_IFMT) == S_IFREG && offset) {
- struct lov_stripe_md *md;
-
- md = lustre_msg_buf(req->rq_repmsg, 2);
- md->lmd_easize = mds->mds_max_mdsize;
- if ((rc = mds_fs_get_md(mds, inode, md)) < 0) {
- CDEBUG(D_INFO, "No md for ino %ld: rc = %d\n",
- inode->i_ino, rc);
- memset(md, 0, md->lmd_easize);
- }
- }
- handle = mds_fs_start(mds, dir, MDS_FSOP_UNLINK);
- if (!handle)
- GOTO(out_unlink_cancel, rc = PTR_ERR(handle));
- rc = vfs_unlink(dir, dchild);
- break;
- default:
- LBUG();
- }
-
- if (!rc)
- rc = mds_update_last_rcvd(mds, handle, req);
- 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;
-}
-
-static int mds_reint_link(struct mds_update_record *rec, int offset,
- struct ptlrpc_request *req)
-{
- struct dentry *de_src = NULL;
- struct dentry *de_tgt_dir = NULL;
- struct dentry *dchild = NULL;
- struct mds_obd *mds = mds_req2mds(req);
- void *handle;
- int rc = 0;
- int 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);
- }
-
- de_tgt_dir = mds_fid2dentry(mds, rec->ur_fid2, NULL);
- if (IS_ERR(de_tgt_dir)) {
- GOTO(out_link_de_src, rc = -ESTALE);
- }
-
- 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_de_tgt_dir, rc = -ESTALE);
- }
-
- if (dchild->d_inode) {
- CERROR("child exists (dir %ld, name %s\n",
- de_tgt_dir->d_inode->i_ino, rec->ur_name);
- GOTO(out_link_dchild, rc = -EEXIST);
- }
-
- OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_LINK_WRITE,
- de_src->d_inode->i_sb->s_dev);
-
- handle = mds_fs_start(mds, de_tgt_dir->d_inode, MDS_FSOP_LINK);
- if (!handle)
- GOTO(out_link_dchild, rc = PTR_ERR(handle));
-
- rc = vfs_link(de_src, de_tgt_dir->d_inode, dchild);
-
- if (!rc)
- rc = mds_update_last_rcvd(mds, handle, req);
-
- 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_de_tgt_dir:
- up(&de_tgt_dir->d_inode->i_sem);
- l_dput(de_tgt_dir);
-out_link_de_src:
- 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, 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_CW : LCK_PW;
- res_id[0] = de_srcdir->d_inode->i_ino;
-
- rc = ldlm_lock_match(obd->obd_namespace, res_id, LDLM_PLAIN,
- NULL, 0, lock_mode, &srclockh);
- if (rc == 0) {
- LDLM_DEBUG_NOLOCK("enqueue res %Lu", 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_CW : LCK_PW;
- res_id[0] = de_tgtdir->d_inode->i_ino;
-
- rc = ldlm_lock_match(obd->obd_namespace, res_id, LDLM_PLAIN,
- NULL, 0, lock_mode, &tgtlockh);
- if (rc == 0) {
- LDLM_DEBUG_NOLOCK("enqueue res %Lu", 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);
-
- double_lock(de_tgtdir, de_srcdir);
-
- 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);
- }
-
- OBD_FAIL_WRITE(OBD_FAIL_MDS_REINT_RENAME_WRITE,
- de_srcdir->d_inode->i_sb->s_dev);
-
- handle = mds_fs_start(mds, de_tgtdir->d_inode, MDS_FSOP_RENAME);
- if (!handle)
- GOTO(out_rename_denew, rc = PTR_ERR(handle));
- lock_kernel();
- rc = vfs_rename(de_srcdir->d_inode, de_old, de_tgtdir->d_inode, de_new,
- NULL);
- unlock_kernel();
-
- if (!rc)
- rc = mds_update_last_rcvd(mds, handle, req);
-
- 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;
- /* 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 %Lu", 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 %Ld, "
- "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 "
- "%Ld: %d\n", res_id[0], rc);
- }
-out_rename_tgtdir:
- double_up(&de_srcdir->d_inode->i_sem, &de_tgtdir->d_inode->i_sem);
- 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,
- [REINT_RECREATE] mds_reint_recreate,
-};
-
-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;
-
- int rc;
-
- if (rec->ur_opcode < 1 || rec->ur_opcode > REINT_MAX) {
- CERROR("opcode %d not valid\n", rec->ur_opcode);
- rc = req->rq_status = -EINVAL;
- RETURN(rc);
- }
-
- push_ctxt(&saved, &mds->mds_ctxt);
- rc = reinters[rec->ur_opcode] (rec, offset, req);
- pop_ctxt(&saved);
-
- 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
-DEFS=
-MODULE = obdclass
-modulefs_DATA = obdclass.o
-EXTRA_PROGRAMS = obdclass
-obdclass_SOURCES = genops.c proc_lustre.c class_obd.c sysctl.c page.c
-
-page.c:
- test -e page.c || ln -sf $(top_srcdir)/lib/page.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 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 <asm/io.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/smp_lock.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 = 0;
-unsigned long obd_fail_loc = 0;
-
-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;
- MOD_INC_USE_COUNT;
- RETURN(0);
-}
-
-/* closing /dev/obd */
-static int obd_class_release(struct inode * inode, struct file * file)
-{
- ENTRY;
-
- if (file->private_data)
- file->private_data = NULL;
-
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-
-inline void obd_data2conn(struct lustre_handle *conn, struct obd_ioctl_data *data)
-{
- conn->addr = data->ioc_addr;
- conn->cookie = data->ioc_cookie;
-}
-
-
-inline void obd_conn2data(struct obd_ioctl_data *data, struct lustre_handle *conn)
-{
- data->ioc_addr = conn->addr;
- data->ioc_cookie = conn->cookie;
-}
-
-
-/* to control /dev/obd */
-static int obd_class_ioctl (struct inode * inode, struct file * filp,
- unsigned int cmd, unsigned long arg)
-{
- char *buf = NULL;
- int len = 0;
- struct obd_ioctl_data *data;
- struct obd_device *obd = filp->private_data;
- struct lustre_handle conn;
- int rw = OBD_BRW_READ;
- int err = 0;
- ENTRY;
-
- down(&obd_conf_sem);
-
- if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS &&
- cmd != OBD_IOC_LIST &&
- 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 = "*";
- else
- status = " ";
- l = snprintf(buf2, remains, "%2d %s %s %s %s\n",
- i, status, obd->obd_type->typ_name,
- obd->obd_name, obd->obd_uuid);
- buf2 +=l;
- remains -=l;
- if (remains <= 0) {
- CERROR("not enough space for device listing\n");
- break;
- }
- }
-
- err = copy_to_user((int *)arg, data, len);
- 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((int *)arg, data, sizeof(*data));
- 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((int *)arg, data, sizeof(*data));
- 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((int *)arg, data, sizeof(*data));
- GOTO(out, err);
- }
-
- case OBD_IOC_ATTACH: {
- struct obd_type *type;
-
- /* have we attached a type to this device */
- if (obd->obd_flags & OBD_ATTACHED) {
- 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);
- }
-
- obd->obd_type = type;
- INIT_LIST_HEAD(&obd->obd_exports);
-
- /* do the attach */
- if (OBP(obd, attach))
- err = OBP(obd,attach)(obd, sizeof(*data), data);
- if (err) {
- 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);
- 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);
- obd->obd_proc_entry =
- proc_lustre_register_obd_device(obd);
- } else {
- CERROR("WARNING: unnamed obd device\n");
- obd->obd_proc_entry = NULL;
- }
-
- if (data->ioc_inlbuf3) {
- int len = strlen(data->ioc_inlbuf3);
- if (len > 37) {
- CERROR("uuid should be shorter than 37 bytes\n");
- 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,
- sizeof(obd->obd_uuid));
- }
-
- 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) ) {
- CERROR("OBD device %d has exports\n",
- obd->obd_minor);
- GOTO(out, err=-EBUSY);
- }
-
- if (obd->obd_name) {
- OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
- obd->obd_name = NULL;
- }
-
- if (obd->obd_proc_entry)
- proc_lustre_release_obd_device(obd);
-
- obd->obd_flags &= ~OBD_ATTACHED;
- obd->obd_type->typ_refcnt--;
- obd->obd_type = NULL;
- 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: {
- obd_data2conn(&conn, data);
-
- err = obd_connect(&conn, obd, NULL);
-
- CDEBUG(D_IOCTL, "assigned export %Lx\n", conn.addr);
- obd_conn2data(data, &conn);
- if (err)
- GOTO(out, err);
-
- err = copy_to_user((int *)arg, data, sizeof(*data));
- GOTO(out, err);
- }
-
- case OBD_IOC_DISCONNECT: {
- obd_data2conn(&conn, data);
- err = obd_disconnect(&conn);
- GOTO(out, err);
- }
-
- case OBD_IOC_DEC_USE_COUNT: {
- MOD_DEC_USE_COUNT;
- GOTO(out, err=0);
- }
-
- case OBD_IOC_CREATE: {
- struct lov_stripe_md *ea;
- obd_data2conn(&conn, data);
-
-
- err = obd_create(&conn, &data->ioc_obdo1, &ea);
- if (err)
- GOTO(out, err);
-
- err = copy_to_user((int *)arg, data, sizeof(*data));
- GOTO(out, err);
- }
-
- case OBD_IOC_GETATTR: {
-
- obd_data2conn(&conn, data);
- err = obd_getattr(&conn, &data->ioc_obdo1, NULL);
- if (err)
- GOTO(out, err);
-
- err = copy_to_user((int *)arg, data, sizeof(*data));
- GOTO(out, err);
- }
-
- case OBD_IOC_SETATTR: {
- obd_data2conn(&conn, data);
- err = obd_setattr(&conn, &data->ioc_obdo1, NULL);
- if (err)
- GOTO(out, err);
-
- err = copy_to_user((int *)arg, data, sizeof(*data));
- GOTO(out, err);
- }
-
- case OBD_IOC_DESTROY: {
- //void *ea;
- obd_data2conn(&conn, data);
-
- err = obd_destroy(&conn, &data->ioc_obdo1, NULL);
- if (err)
- GOTO(out, err);
-
- err = copy_to_user((int *)arg, data, sizeof(*data));
- GOTO(out, err);
- }
-
- case OBD_IOC_BRW_WRITE:
- rw = OBD_BRW_WRITE;
- case OBD_IOC_BRW_READ: {
- struct lov_stripe_md smd;
- struct io_cb_data *cbd = ll_init_cb();
- obd_count pages = 0;
- struct brw_page *pga;
- int j;
- unsigned long off;
- void *from;
-
- if (!cbd)
- GOTO(out, -ENOMEM);
-
- obd_data2conn(&conn, data);
-
- pages = data->ioc_plen1 / PAGE_SIZE;
-
- CDEBUG(D_INODE, "BRW %s with %d pages\n",
- rw == OBD_BRW_READ ? "read" : "write", pages);
- OBD_ALLOC(pga, pages * sizeof(*pga));
- if (!pga) {
- CERROR("no memory for %d BRW per-page data\n", pages);
- GOTO(brw_free, err = -ENOMEM);
- }
-
- memset(&smd, 0, sizeof(smd));
- smd.lmd_object_id = data->ioc_obdo1.o_id;
-
- from = (&data->ioc_pbuf1)[0];
- off = data->ioc_offset;
-
- for (j = 0; j < pages;
- j++, off += PAGE_SIZE, from += PAGE_SIZE) {
- unsigned long to;
-
- to = __get_free_pages(GFP_KERNEL, 0);
- if (!to) {
- /* ||
- copy_from_user((void
- *)to,from,PAGE_SIZE))
- free_pages(to, 0);
- */
- CERROR("no memory for brw pages\n");
- GOTO(brw_cleanup, err = -ENOMEM);
- }
- pga[j].pg = virt_to_page(to);
- pga[j].count = PAGE_SIZE;
- pga[j].off = off;
- pga[j].flag = 0;
- }
-
- err = obd_brw(rw, &conn, &smd, j, pga, ll_sync_io_cb, cbd);
- EXIT;
- brw_cleanup:
- for (j = 0; j < pages; j++)
- if (pga[j].pg != NULL)
- __free_pages(pga[j].pg, 0);
- brw_free:
- OBD_FREE(pga, pages * sizeof(*pga));
- GOTO(out, err);
- }
- default:
- obd_data2conn(&conn, data);
-
- err = obd_iocontrol(cmd, &conn, len, data, NULL);
- if (err)
- GOTO(out, err);
-
- err = copy_to_user((int *)arg, data, len);
- GOTO(out, err);
- }
-
- out:
- if (buf)
- OBD_FREE(buf, len);
- 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
-};
-
-
-EXPORT_SYMBOL(obd_dev);
-EXPORT_SYMBOL(obdo_cachep);
-EXPORT_SYMBOL(obd_memory);
-EXPORT_SYMBOL(obd_fail_loc);
-
-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_connect);
-EXPORT_SYMBOL(class_conn2export);
-EXPORT_SYMBOL(class_rconn2export);
-EXPORT_SYMBOL(class_conn2obd);
-EXPORT_SYMBOL(class_disconnect);
-EXPORT_SYMBOL(class_disconnect_all);
-//EXPORT_SYMBOL(class_multi_setup);
-//EXPORT_SYMBOL(class_multi_cleanup);
-
-static int __init init_obdclass(void)
-{
- int err;
- int i;
-
- printk(KERN_INFO "OBD class driver v0.9, 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;
- }
-
- for (i = 0; i < MAX_OBD_DEVICES; i++) {
- memset(&(obd_dev[i]), 0, sizeof(obd_dev[i]));
- obd_dev[i].obd_minor = i;
- INIT_LIST_HEAD(&obd_dev[i].obd_exports);
- }
-
- err = obd_init_caches();
- if (err)
- return err;
- obd_sysctl_init();
- return 0;
-}
-
-static void __exit cleanup_obdclass(void)
-{
- int i;
- 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();
- CERROR("obd memory leaked: %ld bytes\n", obd_memory);
- EXIT;
-}
-
-MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
-MODULE_DESCRIPTION("Lustre Class Driver v1.0");
-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:
-*
- * linux/fs/ext2_obd/sim_obd.c
- * Copyright (C) 2001 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
- *
- */
-
-#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>
-
-extern struct list_head obd_types;
-extern struct obd_device obd_dev[MAX_OBD_DEVICES];
-kmem_cache_t *obdo_cachep = NULL;
-kmem_cache_t *export_cachep = NULL;
-kmem_cache_t *import_cachep = NULL;
-
-/*
- * 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, char *nm)
-{
- struct obd_type *type;
-
- ENTRY;
-
- if (class_search_type(nm)) {
- CDEBUG(D_IOCTL, "Type %s already registered\n", nm);
- RETURN(-EEXIST);
- }
-
- OBD_ALLOC(type, sizeof(*type));
- if (!type)
- RETURN(-ENOMEM);
- INIT_LIST_HEAD(&type->typ_chain);
- MOD_INC_USE_COUNT;
- list_add(&type->typ_chain, &obd_types);
- type->typ_ops = ops;
- type->typ_name = nm;
- RETURN(0);
-}
-
-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);
- RETURN(-EBUSY);
- }
-
- list_del(&type->typ_chain);
- OBD_FREE(type, sizeof(*type));
- 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 *name)
-{
- int res = -1;
- int i;
-
- for (i=0; i < MAX_OBD_DEVICES; i++) {
- struct obd_device *obd = &obd_dev[i];
- if (obd->obd_name && strncmp(name, obd->obd_uuid, 37) == 0) {
- res = i;
- return res;
- }
- }
-
- return res;
-}
-
-
-struct obd_device *class_uuid2obd(char *name)
-{
- int i;
-
- for (i=0; i < MAX_OBD_DEVICES; i++) {
- struct obd_device *obd = &obd_dev[i];
- if (obd->obd_name && strncmp(name, obd->obd_uuid, 37) == 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 obdo_cachep\n");
- obdo_cachep = NULL;
- }
- if (import_cachep) {
- rc = kmem_cache_destroy(import_cachep);
- if (rc)
- CERROR("Cannot destory import_cachep\n");
- import_cachep = NULL;
- }
- if (export_cachep) {
- rc = kmem_cache_destroy(export_cachep);
- if (rc)
- CERROR("Cannot destory import_cachep\n");
- export_cachep = NULL;
- }
- EXIT;
-}
-
-int obd_init_caches(void)
-{
- ENTRY;
- if (obdo_cachep == NULL) {
- obdo_cachep = kmem_cache_create("obdo_cache",
- sizeof(struct obdo),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (obdo_cachep == NULL)
- GOTO(out, -ENOMEM);
- }
-
- if (export_cachep == NULL) {
- export_cachep = kmem_cache_create("export_cache",
- sizeof(struct obd_export),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (export_cachep == NULL)
- GOTO(out, -ENOMEM);
- }
-
- if (import_cachep == NULL) {
- import_cachep = kmem_cache_create("import_cache",
- sizeof(struct obd_import),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (import_cachep == NULL)
- 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;
-
- 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 %Lx cookie %Lx\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_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(__u64));
- export->exp_obd = obddev;
- INIT_LIST_HEAD(&export->exp_mds_data.med_open_head);
- list_add(&(export->exp_chain), &export->exp_obd->obd_exports);
- return export;
-}
-
-/* a connection defines an export context in which preallocation can
- be managed. */
-int class_connect (struct lustre_handle *conn, struct obd_device *obd,
- char *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;
-
- export->exp_rconnh.addr = conn->addr;
- export->exp_rconnh.cookie = conn->cookie;
-
- 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_rconn2export(struct lustre_handle *conn, struct lustre_handle *rconn)
-{
- struct obd_export *export = class_conn2export(conn);
-
- if (!export)
- return -EINVAL;
-
- export->exp_rconnh.addr = rconn->addr;
- export->exp_rconnh.cookie = rconn->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 %Lx\n", conn->addr);
- RETURN(-EINVAL);
- } else
- CDEBUG(D_IOCTL, "disconnect: addr %Lx cookie %Lx\n",
- (long long)conn->addr, (long long)conn->cookie);
- list_del(&export->exp_chain);
- kmem_cache_free(export_cachep, export);
-
- RETURN(0);
-}
-
-void class_disconnect_all(struct obd_device *obddev)
-{
- struct list_head *tmp, *next;
-
- list_for_each_safe(tmp, next, &obddev->obd_exports) {
- struct obd_export *export;
- struct lustre_handle conn;
-
- export = list_entry(tmp, struct obd_export, exp_chain);
- conn.addr = (__u64) (unsigned long)export;
- conn.cookie = export->exp_cookie;
- obd_disconnect(&conn);
- }
-}
-
-#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:
- *
- * proc_lustre.c manages /proc/lustre
- *
- * Copyright (c) 2001 Rumi Zahir <rumi.zahir@intel.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.
- */
-
-/* OBD devices materialize in /proc as a directory:
- * /proc/lustre/obd/<number>
- * when /dev/obd<number> is opened. When the device is closed, the
- * directory entry disappears.
- *
- * For each open OBD device, code in this file also creates a file
- * named <status>. "cat /proc/lustre/obd/<number>/status" gives
- * information about the OBD device's configuration.
- * The class driver manages the "status" entry.
- *
- * Other logical drivers can create their own entries. For example,
- * the obdtrace driver creates /proc/lustre/obd/<obdid>/stats entry.
- *
- * This file defines three functions
- * proc_lustre_register_obd_device() - called at device attach time
- * proc_lustre_release_obd_device() - called at detach
- * proc_lustre_remove_obd_entry()
- * that dynamically create/delete /proc/lustre/obd entries:
- *
- * proc_lustre_register_obd_device() registers an obd device,
- * and, if this is the first OBD device, creates /proc/lustre/obd.
- *
- * proc_lustre_release_obd_device() removes device information
- * from /proc/lustre/obd, and if this is the last OBD device
- * removes /proc/lustre/obd.
- *
- * proc_lustre_remove_obd_entry() removes a
- * /proc/lustre/obd/<obdid>/ entry by name. This is the only
- * function that is exported to other modules.
- */
-
-#define EXPORT_SYMTAB
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/proc_fs.h>
-
-#define DEBUG_SUBSYSTEM S_CLASS
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-
-#ifdef CONFIG_PROC_FS
-extern struct proc_dir_entry proc_root;
-static struct proc_dir_entry *proc_lustre_dir_entry = NULL;
-static struct proc_dir_entry *proc_lustre_obd_dir_entry = NULL;
-
-static int read_lustre_status(char *page, char **start, off_t offset,
- int count, int *eof, void *data)
-{
- struct obd_device * obddev = (struct obd_device *)data;
- int p;
-
-#warning FIXME: This function is madness, completely unsafe, a disaster waiting to happen.
-
- p = sprintf(&page[0], "device=%d\n", obddev->obd_minor);
- p += sprintf(&page[p], "name=%s\n", MKSTR(obddev->obd_name));
- p += sprintf(&page[p], "uuid=%s\n", obddev->obd_uuid);
- p += sprintf(&page[p], "attached=1\n");
- p += sprintf(&page[p], "type=%s\n", MKSTR(obddev->obd_type->typ_name));
-
- if (obddev->obd_flags & OBD_SET_UP)
- p += sprintf(&page[p], "setup=1\n");
-
- /* print exports */
- {
- struct list_head *lh;
- struct obd_export *export = NULL;
-
- lh = &obddev->obd_exports;
- while ((lh = lh->next) != &obddev->obd_exports) {
- p += sprintf(&page[p],
- ((export == NULL) ? ", connections(" : ",") );
- export = list_entry(lh, struct obd_export, exp_chain);
- p += sprintf(&page[p], "%p", export);
- }
- if (export != 0) { /* there was at least one export */
- p += sprintf(&page[p], ")");
- }
- }
-
- p += sprintf(&page[p], "\n");
-
- /* Compute eof and return value */
- if (offset + count >= p) {
- *eof = 1;
- return (p - offset);
- }
- return count;
-}
-
-struct proc_dir_entry *proc_lustre_register_obd_device(struct obd_device *obd)
-{
- struct proc_dir_entry *obd_dir;
- struct proc_dir_entry *obd_status = NULL;
-
- if (!proc_lustre_dir_entry) {
- proc_lustre_dir_entry = proc_mkdir("lustre", &proc_root);
- if (IS_ERR(proc_lustre_dir_entry))
- return 0;
-
- proc_lustre_obd_dir_entry =
- proc_mkdir("devices", proc_lustre_dir_entry);
- if (IS_ERR(proc_lustre_obd_dir_entry))
- return 0;
- }
- obd_dir = proc_mkdir(obd->obd_name, proc_lustre_obd_dir_entry);
-
- if (obd_dir)
- obd_status = create_proc_entry("status", S_IRUSR | S_IFREG,
- obd_dir);
-
- if (obd_status) {
- obd_status->read_proc = read_lustre_status;
- obd_status->data = (void *)obd;
- }
-
- return obd_dir;
-}
-
-void proc_lustre_remove_obd_entry(const char *name, struct obd_device *obd)
-{
- struct proc_dir_entry *obd_entry = NULL;
- struct proc_dir_entry *obd_dir = obd->obd_proc_entry;
-
- remove_proc_entry(name, obd_dir);
-
- while (obd_dir->subdir == NULL) {
- /* if we removed last entry in this directory, then
- * remove parent directory unless this is /proc itself */
- if (obd_dir == &proc_root)
- break;
-
- obd_entry = obd_dir;
- obd_dir = obd_dir->parent;
-
- /* If /proc/lustre/obd/foo or /proc/lustre/obd or
- * /proc/lustre is being removed, then reset internal
- * variables */
-
- if (obd_entry == obd->obd_proc_entry)
- obd->obd_proc_entry = NULL; /* /proc/lustre/obd/foo */
- else if (obd_entry == proc_lustre_obd_dir_entry)
- proc_lustre_obd_dir_entry = NULL; /* /proc/lustre/obd */
- else if (obd_entry == proc_lustre_dir_entry)
- proc_lustre_dir_entry = NULL; /* /proc/lustre */
-
- remove_proc_entry(obd_entry->name, obd_dir);
- }
-}
-
-void proc_lustre_release_obd_device(struct obd_device *obd)
-{
- proc_lustre_remove_obd_entry("status", obd);
-}
-
-
-#else /* CONFIG_PROC_FS */
-
-struct proc_dir_entry *proc_lustre_register_obd_device(struct obd_device *obd)
-{
- return 0;
-}
-
-void proc_lustre_remove_obd_entry(const char* name, struct obd_device *obd)
-{
-}
-
-void proc_lustre_release_obd_device(struct obd_device *obd)
-{
-}
-
-#endif /* CONFIG_PROC_FS */
-
-EXPORT_SYMBOL(proc_lustre_remove_obd_entry);
+++ /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_TIMEOUT 3 /* timeout on upcalls to become intrble */
-#define OBD_HARD 4 /* mount type "hard" or "soft" */
-#define OBD_VARS 5
-#define OBD_INDEX 6
-#define OBD_RESET 7
-
-#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},
- { 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
-.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
-
-obdecho_SOURCES = echo.c
-
-include $(top_srcdir)/Rules
-
+++ /dev/null
-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * linux/fs/ext2_obd/ext2_obd.c
- *
- * Copyright (C) 2001 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>
- */
-
-static char rcsid[] __attribute ((unused)) = "$Id: echo.c,v 1.22 2002/08/12 22:25:53 pschwan Exp $";
-#define OBDECHO_VERSION "$Revision: 1.22 $"
-
-#define EXPORT_SYMTAB
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/locks.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_dlm.h>
-
-extern struct obd_device obd_dev[MAX_OBD_DEVICES];
-static struct obdo OA;
-static obd_count GEN;
-static long echo_pages = 0;
-
-static atomic_t echo_page_rws;
-static atomic_t echo_getattrs;
-
-#define ECHO_PROC_STAT "sys/obdecho"
-
-int
-echo_proc_read (char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- int len;
- int attrs = atomic_read (&echo_getattrs);
- int pages = atomic_read (&echo_page_rws);
-
- *eof = 1;
- if (off != 0)
- return (0);
-
- len = sprintf (page, "%d %d\n", pages, attrs);
-
- *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 stats counters */
- atomic_set (&echo_page_rws, 0);
- atomic_set (&echo_getattrs, 0);
-
- return (count);
-}
-
-void
-echo_proc_init(void)
-{
- struct proc_dir_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,
- char *cluuid)
-{
- int rc;
-
- MOD_INC_USE_COUNT;
- rc = class_connect(conn, obd, NULL);
-
- 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 int echo_getattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- memcpy(oa, &OA, sizeof(*oa));
- oa->o_mode = ++GEN;
-
- atomic_inc (&echo_getattrs);
-
- return 0;
-}
-
-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 niobuf_local *r = res;
- int rc = 0;
- int i;
-
- ENTRY;
-
- memset(res, 0, sizeof(*res) * niocount);
-
- CDEBUG(D_PAGE, "%s %d obdos with %d IOs\n",
- cmd == OBD_BRW_READ ? "reading" : "writing", objcount, niocount);
-
- for (i = 0; i < objcount; i++, obj++) {
- int j;
-
- for (j = 0 ; j < obj->ioo_bufcnt ; j++, nb++, r++) {
- unsigned long address;
-
- address = get_zeroed_page(GFP_KERNEL);
- if (!address) {
- CERROR("can't get new page %d/%d for id %Ld\n",
- j, obj->ioo_bufcnt,
- (unsigned long long)obj->ioo_id);
- GOTO(preprw_cleanup, rc = -ENOMEM);
- }
- echo_pages++;
-
- r->offset = nb->offset;
- r->page = virt_to_page(address);
- r->addr = kmap(r->page);
- r->len = nb->len;
- }
- }
- CDEBUG(D_PAGE, "%ld pages allocated after prep\n", echo_pages);
-
- 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);
- echo_pages--;
- }
- 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 niobuf_local *r = res;
- int rc = 0;
- int i;
- ENTRY;
-
- CDEBUG(D_PAGE, "%s %d obdos with %d IOs\n",
- cmd == OBD_BRW_READ ? "reading" : "writing", objcount, niocount);
-
- if (niocount && !r) {
- CERROR("NULL res niobuf with niocount %d\n", niocount);
- RETURN(-EINVAL);
- }
-
- for (i = 0; i < objcount; i++, obj++) {
- int j;
-
- for (j = 0 ; j < obj->ioo_bufcnt ; j++, r++) {
- struct page *page = r->page;
- unsigned long addr;
-
- if (!page ||
- !(addr = (unsigned long)page_address(page)) ||
- !kern_addr_valid(addr)) {
-
- CERROR("bad page %p, id %Ld (%d), buf %d/%d\n",
- page, (unsigned long long)obj->ioo_id, i,
- j, obj->ioo_bufcnt);
- GOTO(commitrw_cleanup, rc = -EFAULT);
- }
-
- atomic_inc (&echo_page_rws);
-
- kunmap(page);
- __free_pages(page, 0);
- echo_pages--;
- }
- }
- CDEBUG(D_PAGE, "%ld pages remain after commit\n", echo_pages);
- 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);
- __free_pages(page, 0);
- echo_pages--;
- }
- 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);
- }
-
- RETURN(0);
-}
-
-static int echo_cleanup(struct obd_device *obddev)
-{
- ENTRY;
-
- ldlm_namespace_free(obddev->obd_namespace);
-
- RETURN(0);
-}
-
-struct obd_ops echo_obd_ops = {
- o_connect: echo_connect,
- o_disconnect: echo_disconnect,
- o_getattr: echo_getattr,
- o_preprw: echo_preprw,
- o_commitrw: echo_commitrw,
- o_setup: echo_setup,
- o_cleanup: echo_cleanup
-};
-
-static int __init obdecho_init(void)
-{
- printk(KERN_INFO "Echo OBD driver " OBDECHO_VERSION " info@clusterfs.com\n");
-
- echo_proc_init();
-
- return class_register_type(&echo_obd_ops, OBD_ECHO_DEVICENAME);
-}
-
-static void __exit obdecho_exit(void)
-{
- echo_proc_fini ();
-
- CERROR("%ld prep/commitrw pages leaked\n", echo_pages);
- 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
-.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=page.c simple.c
-simple.c:
- test -e simple.c || ln -sf $(top_srcdir)/lib/simple.c
-page.c:
- test -e page.c || ln -sf $(top_srcdir)/lib/page.c
-
-FILTERC = filter.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/filter/filter.c
- *
- * Copyright (C) 2001 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_FILTER
-
-#include <linux/module.h>
-#include <linux/lustre_dlm.h>
-#include <linux/obd_filter.h>
-#include <linux/ext3_jbd.h>
-#include <linux/quotaops.h>
-#include <linux/init.h>
-
-extern struct obd_device obd_dev[MAX_OBD_DEVICES];
-long filter_memory;
-
-#define FILTER_ROOTINO 2
-
-#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/%Ld", obd_mode_to_type(mode),
- (unsigned long long)id);
-}
-
-/* setup the object store with correct subdirectories */
-static int filter_prep(struct obd_device *obddev)
-{
- struct obd_run_ctxt saved;
- struct filter_obd *filter = &obddev->u.filter;
- struct dentry *dentry;
- struct file *file;
- struct inode *inode;
- int rc = 0;
- char rootid[128];
- __u64 lastino = 2;
- int mode = 0;
-
- push_ctxt(&saved, &filter->fo_ctxt);
- 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);
- }
- CDEBUG(D_INODE, "putting P: %p, count = %d\n", dentry,
- atomic_read(&dentry->d_count) - 1);
- 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);
- }
- CDEBUG(D_INODE, "putting D: %p, count = %d\n", dentry,
- atomic_read(&dentry->d_count) - 1);
- dput(dentry);
-
- /*
- * 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;
- }
-
- filter_id(rootid, FILTER_ROOTINO, S_IFDIR);
- file = filp_open(rootid, O_RDWR | O_CREAT, 0755);
- if (IS_ERR(file)) {
- rc = PTR_ERR(file);
- CERROR("OBD filter: cannot open/create root %s: rc = %d\n",
- rootid, rc);
- GOTO(out_O_mode, rc);
- }
- filp_close(file, 0);
-
- 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_lastino = cpu_to_le64(lastino);
- ssize_t retval = file->f_op->write(file, (char *)&disk_lastino,
- sizeof(disk_lastino),
- &file->f_pos);
- if (retval != sizeof(disk_lastino)) {
- CDEBUG(D_INODE, "OBD filter: error writing lastino\n");
- filp_close(file, 0);
- GOTO(out_O_mode, rc = -EIO);
- }
- } else {
- __u64 disk_lastino;
- ssize_t retval = file->f_op->read(file, (char *)&disk_lastino,
- sizeof(disk_lastino),
- &file->f_pos);
- if (retval != sizeof(disk_lastino)) {
- CDEBUG(D_INODE, "OBD filter: error reading lastino\n");
- filp_close(file, 0);
- GOTO(out_O_mode, rc = -EIO);
- }
- lastino = le64_to_cpu(disk_lastino);
- }
- filter->fo_lastino = lastino;
- filp_close(file, 0);
-
- rc = 0;
- out:
- pop_ctxt(&saved);
-
- return(rc);
-
-out_O_mode:
- while (mode-- > 0) {
- struct dentry *dentry = filter->fo_dentry_O_mode[mode];
- if (dentry) {
- CDEBUG(D_INODE, "putting O/%s: %p, count = %d\n",
- obd_type_by_mode[mode], dentry,
- atomic_read(&dentry->d_count) - 1);
- dput(dentry);
- filter->fo_dentry_O_mode[mode] = NULL;
- }
- }
-out_O:
- CDEBUG(D_INODE, "putting O: %p, count = %d\n", filter->fo_dentry_O,
- atomic_read(&filter->fo_dentry_O->d_count) - 1);
- 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 *obddev)
-{
- struct obd_run_ctxt saved;
- struct filter_obd *filter = &obddev->u.filter;
- __u64 disk_lastino;
- long rc;
- struct file *file;
- int mode;
-
- push_ctxt(&saved, &filter->fo_ctxt);
- 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_lastino = cpu_to_le64(filter->fo_lastino);
- rc = file->f_op->write(file, (char *)&disk_lastino,
- sizeof(disk_lastino), &file->f_pos);
- if (rc != sizeof(disk_lastino))
- CERROR("OBD filter: error writing lastino: 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) {
- CDEBUG(D_INODE, "putting O/%s: %p, count = %d\n",
- obd_type_by_mode[mode], dentry,
- atomic_read(&dentry->d_count) - 1);
- dput(dentry);
- filter->fo_dentry_O_mode[mode] = NULL;
- }
- }
- CDEBUG(D_INODE, "putting O: %p, count = %d\n", filter->fo_dentry_O,
- atomic_read(&filter->fo_dentry_O->d_count) - 1);
- dput(filter->fo_dentry_O);
-out:
- pop_ctxt(&saved);
-}
-
-
-static __u64 filter_next_id(struct obd_device *obddev)
-{
- __u64 id;
-
- spin_lock(&obddev->u.filter.fo_lock);
- obddev->u.filter.fo_lastino++;
- id = obddev->u.filter.fo_lastino;
- spin_unlock(&obddev->u.filter.fo_lock);
-
- /* FIXME: write the lastino 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 *obddev,
- struct dentry *dparent,
- __u64 id, __u32 type)
-{
- struct super_block *sb = obddev->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 %Lu has bad type: %o\n", __FUNCTION__,
- (unsigned long long)id, type);
- RETURN(ERR_PTR(-EINVAL));
- }
-
- len = sprintf(name, "%Ld", id);
- CDEBUG(D_INODE, "opening object O/%s/%s\n", obd_mode_to_type(type),
- name);
- dchild = lookup_one_len(name, dparent, len);
- 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));
-
- if (IS_ERR(dchild)) {
- CERROR("child lookup error %ld\n", PTR_ERR(dchild));
- RETURN(dchild);
- }
-
- RETURN(dchild);
-}
-
-static struct file *filter_obj_open(struct obd_device *obddev,
- __u64 id, __u32 type)
-{
- struct super_block *sb = obddev->u.filter.fo_sb;
- 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 %Lu\n", (unsigned long long)id);
- RETURN(ERR_PTR(-ESTALE));
- }
-
- if (!(type & S_IFMT)) {
- CERROR("OBD %s, no type (%Ld), mode %o!\n", __FUNCTION__,
- (unsigned long long)id, type);
- RETURN(ERR_PTR(-EINVAL));
- }
-
- filter_id(name, id, type);
- push_ctxt(&saved, &obddev->u.filter.fo_ctxt);
- file = filp_open(name, O_RDONLY | O_LARGEFILE, 0 /* type? */);
- pop_ctxt(&saved);
-
- CDEBUG(D_INODE, "opening obdo %s: rc = %p\n", name, file);
-
- if (IS_ERR(file))
- file = NULL;
- RETURN(file);
-}
-
-static struct dentry *filter_parent(struct obd_device *obddev, obd_mode mode)
-{
- struct filter_obd *filter = &obddev->u.filter;
-
- return filter->fo_dentry_O_mode[(mode & S_IFMT) >> S_SHIFT];
-}
-
-
-static struct inode *filter_inode_from_obj(struct obd_device *obddev,
- __u64 id, __u32 type)
-{
- struct dentry *dentry;
- struct inode *inode;
-
- dentry = filter_fid2dentry(obddev, filter_parent(obddev, type),
- id, type);
- if (IS_ERR(dentry)) {
- CERROR("%s: lookup failed: rc = %ld\n", __FUNCTION__,
- PTR_ERR(dentry));
- RETURN(NULL);
- }
-
- lock_kernel();
- inode = iget(dentry->d_inode->i_sb, dentry->d_inode->i_ino);
- unlock_kernel();
- CDEBUG(D_INODE, "put child %p, count = %d\n", dentry,
- atomic_read(&dentry->d_count) - 1);
- dput(dentry);
- CDEBUG(D_INODE, "got inode %p (%ld), count = %d\n", inode, inode->i_ino,
- atomic_read(&inode->i_count));
- return inode;
-}
-
-/* obd methods */
-static int filter_connect(struct lustre_handle *conn, struct obd_device *obd,
- char *cluuid)
-{
- int rc;
- ENTRY;
- MOD_INC_USE_COUNT;
- rc = class_connect(conn, obd, cluuid);
- if (rc)
- MOD_DEC_USE_COUNT;
- RETURN(rc);
-}
-
-static int filter_disconnect(struct lustre_handle *conn)
-{
- int rc;
- ENTRY;
-
- 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 *obddev, 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 = &obddev->u.filter;;
- filter->fo_sb = mnt->mnt_root->d_inode->i_sb;
- /* XXX is this even possible if do_kern_mount succeeded? */
- if (!filter->fo_sb)
- GOTO(err_put, err = -ENODEV);
-
- filter->fo_vfsmnt = mnt;
- filter->fo_fstype = strdup(data->ioc_inlbuf2);
-
- 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(obddev);
- if (err)
- GOTO(err_kfree, err);
- spin_lock_init(&filter->fo_lock);
-
- obddev->obd_namespace =
- ldlm_namespace_new("filter-tgt", LDLM_NAMESPACE_SERVER);
- if (obddev->obd_namespace == NULL)
- LBUG();
-
- RETURN(0);
-
-err_kfree:
- kfree(filter->fo_fstype);
-err_put:
- 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 * obddev)
-{
- struct super_block *sb;
- ENTRY;
-
- if (!list_empty(&obddev->obd_exports)) {
- CERROR("still has clients!\n");
- class_disconnect_all(obddev);
- if (!list_empty(&obddev->obd_exports)) {
- CERROR("still has exports after forced cleanup?\n");
- RETURN(-EBUSY);
- }
- }
-
- ldlm_namespace_free(obddev->obd_namespace);
-
- sb = obddev->u.filter.fo_sb;
- if (!obddev->u.filter.fo_sb)
- RETURN(0);
-
- filter_post(obddev);
-
- shrink_dcache_parent(sb->s_root);
- unlock_kernel();
- mntput(obddev->u.filter.fo_vfsmnt);
- obddev->u.filter.fo_sb = 0;
- kfree(obddev->u.filter.fo_fstype);
-
- lock_kernel();
-
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-
-static inline void filter_from_inode(struct obdo *oa, struct inode *inode)
-{
- int type = oa->o_mode & S_IFMT;
- ENTRY;
-
- CDEBUG(D_INFO, "src inode %ld, dst obdo %ld valid 0x%08x\n",
- inode->i_ino, (long)oa->o_id, oa->o_valid);
- obdo_from_inode(oa, inode);
- 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 int filter_getattr(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *md)
-{
- struct obd_device *obddev = class_conn2obd(conn);
- struct dentry *dentry;
- ENTRY;
-
- if (!class_conn2export(conn)) {
- CDEBUG(D_IOCTL, "fatal: invalid client %Lx\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- obddev = class_conn2obd(conn);
- dentry = filter_fid2dentry(obddev, filter_parent(obddev, oa->o_mode),
- oa->o_id, oa->o_mode);
- if (IS_ERR(dentry))
- RETURN(PTR_ERR(dentry));
-
- oa->o_valid &= ~OBD_MD_FLID;
- filter_from_inode(oa, dentry->d_inode);
-
- dput(dentry);
- RETURN(0);
-}
-
-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;
-
- iattr_from_obdo(&iattr, oa);
- iattr.ia_mode = (iattr.ia_mode & ~S_IFMT) | S_IFREG;
- dentry = filter_fid2dentry(obd, filter_parent(obd, iattr.ia_mode),
- oa->o_id, iattr.ia_mode);
- if (IS_ERR(dentry))
- RETURN(PTR_ERR(dentry));
-
- inode = dentry->d_inode;
- lock_kernel();
- if (iattr.ia_mode & ATTR_SIZE)
- down(&inode->i_sem);
- push_ctxt(&saved, &obd->u.filter.fo_ctxt);
- if (inode->i_op->setattr)
- rc = inode->i_op->setattr(dentry, &iattr);
- else
- rc = inode_setattr(inode, &iattr);
- pop_ctxt(&saved);
- if (iattr.ia_mode & ATTR_SIZE) {
- up(&inode->i_sem);
- oa->o_valid = OBD_MD_FLBLOCKS | OBD_MD_FLCTIME | OBD_MD_FLMTIME;
- obdo_from_inode(oa, inode);
- }
- unlock_kernel();
-
- CDEBUG(D_INODE, "put dentry %p, count = %d\n", inode,
- atomic_read(&dentry->d_count) - 1);
- dput(dentry);
- RETURN(rc);
-}
-
-static int filter_open(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea)
-{
- struct obd_device *obd;
- struct dentry *dentry;
- /* ENTRY; */
-
- if (!class_conn2export(conn)) {
- CDEBUG(D_IOCTL, "fatal: invalid client %Lx\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- obd = class_conn2obd(conn);
- dentry = filter_fid2dentry(obd, filter_parent(obd, oa->o_mode),
- oa->o_id, oa->o_mode);
- if (IS_ERR(dentry))
- RETURN(PTR_ERR(dentry));
-
- return 0;
-} /* filter_open */
-
-static int filter_close(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea)
-{
- struct obd_device *obd;
- struct dentry *dentry;
- /* ENTRY; */
-
- obd = class_conn2obd(conn);
- if (!obd) {
- CDEBUG(D_IOCTL, "fatal: invalid client %Lx\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- dentry = filter_fid2dentry(obd, filter_parent(obd, oa->o_mode),
- oa->o_id, oa->o_mode);
- if (IS_ERR(dentry))
- RETURN(PTR_ERR(dentry));
-
- CDEBUG(D_INODE, "put dentry %p, count = %d\n", dentry,
- atomic_read(&dentry->d_count) - 1);
- dput(dentry); /* for the close */
- CDEBUG(D_INODE, "put dentry %p, count = %d\n", dentry,
- atomic_read(&dentry->d_count) - 1);
- dput(dentry); /* for this call */
- return 0;
-} /* filter_close */
-
-static int filter_create(struct lustre_handle* conn, struct obdo *oa,
- struct lov_stripe_md **ea)
-{
- char name[64];
- struct obd_run_ctxt saved;
- struct file *file;
- int mode;
- struct obd_device *obd = class_conn2obd(conn);
- struct iattr;
- ENTRY;
-
- if (!obd) {
- CERROR("invalid client %Lx\n", conn->addr);
- return -EINVAL;
- }
-
- oa->o_id = filter_next_id(obd);
- if (!(oa->o_mode && S_IFMT)) {
- CERROR("filter obd: no type!\n");
- return -ENOENT;
- }
-
- filter_id(name, oa->o_id, oa->o_mode);
- mode = (oa->o_mode & ~S_IFMT) | S_IFREG;
- push_ctxt(&saved, &obd->u.filter.fo_ctxt);
- file = filp_open(name, O_RDONLY | O_CREAT, mode);
- pop_ctxt(&saved);
- if (IS_ERR(file)) {
- CERROR("Error mknod obj %s, err %ld\n", name, PTR_ERR(file));
- return -ENOENT;
- }
- filp_close(file, 0);
-
- /* 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 |
- OBD_MD_FLUID | OBD_MD_FLGID;
-
- /* XXX Hmm, shouldn't we copy the fields into the obdo here? */
- return 0;
-}
-
-static int filter_destroy(struct lustre_handle *conn, struct obdo *oa,
- struct lov_stripe_md *ea)
-{
- struct obd_device *obd;
- struct filter_obd *filter;
- struct obd_run_ctxt saved;
- struct inode *inode;
- struct dentry *dir_dentry, *object_dentry;
- int rc;
- ENTRY;
-
- obd = class_conn2obd(conn);
- if (!obd) {
- CERROR("invalid client %Lx\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- CDEBUG(D_INODE, "destroying object %Ld\n", oa->o_id);
-
- dir_dentry = filter_parent(obd, oa->o_mode);
- down(&dir_dentry->d_inode->i_sem);
-
- object_dentry = filter_fid2dentry(obd, dir_dentry, oa->o_id,
- oa->o_mode);
- if (IS_ERR(object_dentry))
- GOTO(out, rc = -ENOENT);
-
- inode = object_dentry->d_inode;
- if (inode == NULL) {
- CERROR("trying to destroy negative inode %Ld!\n", oa->o_id);
- GOTO(out, rc = -ENOENT);
- }
-
- if (inode->i_nlink != 1) {
- CERROR("destroying inode with nlink = %d\n", inode->i_nlink);
- LBUG();
- inode->i_nlink = 1;
- }
- inode->i_mode = S_IFREG;
-
- filter = &obd->u.filter;
- push_ctxt(&saved, &filter->fo_ctxt);
-
- rc = vfs_unlink(dir_dentry->d_inode, object_dentry);
- pop_ctxt(&saved);
- CDEBUG(D_INODE, "put child %p, count = %d\n", object_dentry,
- atomic_read(&object_dentry->d_count) - 1);
- 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 *md,
- obd_off start, obd_off end)
-{
- int error;
- ENTRY;
-
- if (end != 0xffffffffffffffff)
- CERROR("PUNCH not supported, only truncate works\n");
-
- CDEBUG(D_INODE, "calling truncate for object #%Ld, valid = %x, "
- "o_size = %Ld\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 *md, obd_count oa_bufs,
- struct brw_page *pga, brw_callback_t callback,
- struct io_cb_data *data)
-{
- struct obd_run_ctxt saved;
- struct super_block *sb;
- int pnum; /* index to pages (bufs) */
- unsigned long retval;
- int error;
- struct file *file;
- struct obd_device *obd = class_conn2obd(conn);
- int pg;
- ENTRY;
-
- if (!obd) {
- CDEBUG(D_IOCTL, "invalid client %Lx\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- sb = obd->u.filter.fo_sb;
- push_ctxt(&saved, &obd->u.filter.fo_ctxt);
- pnum = 0; /* pnum indexes buf 0..num_pages */
-
- file = filter_obj_open(obd, md->lmd_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,%ld) "
- "off count (%Ld,%Ld)\n",
- cmd, pnum, file->f_dentry->d_inode->i_ino,
- (unsigned long)pga[pnum].off >> PAGE_CACHE_SHIFT,
- (unsigned long long)pga[pnum].off,
- (unsigned long long)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(pages[pnum]);
- 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(pages[pnum]);
-
- 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);
- error = (retval >= 0) ? 0 : retval;
- return error;
-}
-
-
-struct inode *ioobj_to_inode(struct lustre_handle *conn, struct obd_ioobj *o)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct super_block *sb = obd->u.filter.fo_sb;
- struct inode *inode = NULL;
- ENTRY;
-
- if (!sb || !sb->s_dev) {
- CDEBUG(D_SUPER, "fatal: device not initialized.\n");
- RETURN(NULL);
- }
-
- if (!o->ioo_id) {
- CDEBUG(D_INODE, "fatal: invalid obdo %lu\n", (long)o->ioo_id);
- RETURN(NULL);
- }
-
- inode = filter_inode_from_obj(obd, o->ioo_id, S_IFREG);
- if (!inode || inode->i_nlink == 0 || is_bad_inode(inode)) {
- CERROR("from obdo - fatal: invalid inode %ld (%s).\n",
- (long)o->ioo_id, inode ? inode->i_nlink ? "bad inode" :
- "no links" : "NULL");
- iput(inode);
- RETURN(NULL);
- }
-
- RETURN(inode);
-}
-
-/*
- * 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;
- }
-
- 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;
-
- /* Assumes ext3 and extN have same sb_info layout, but avoids issues
- * with having extN built properly before filterobd for now.
- */
- journal = EXT3_SB(filter->fo_sb)->s_journal;
- 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;
- }
-
- handle = journal_start(journal, needed);
- 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.
- */
- rc = journal_stop((handle_t *)handle);
-
- 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;
-}
-
-struct page *filter_get_page_write(struct inode *inode, unsigned long index,
- struct niobuf_local *lnb)
-{
- struct address_space *mapping = inode->i_mapping;
- struct page *page;
- int rc;
-
- //ASSERT_PAGE_INDEX(index, GOTO(err, rc = -EINVAL));
- page = grab_cache_page_nowait(mapping, index); /* locked page */
-
- /* This page is currently locked, so get a temporary page instead */
- if (!page) {
- unsigned long addr;
- /* not a real error, just seeing if/when this really happens
- CDEBUG(D_PAGE, "ino %ld page %ld locked\n", inode->i_ino,index);
- */
- CERROR("writing 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);
- }
- page = virt_to_page(addr);
- kmap(page);
- page->index = index;
- lnb->flags |= N_LOCAL_TEMP_PAGE;
- } else if (!IS_ERR(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.
- */
- kmap(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);
-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 (err) {
- unsigned block_start, block_end;
- struct buffer_head *bh, *head = page->buffers;
- unsigned blocksize = head->b_size;
- void *addr = page_address(page);
-
- /* not really an error, 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);
- }
- }
-
- 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 *b = nb;
- struct niobuf_local *r = res;
- void *journal_save = NULL;
- int rc = 0;
- int i;
- ENTRY;
-
- memset(res, 0, sizeof(*res) * niocount);
- obd = class_conn2obd(conn);
-
- push_ctxt(&saved, &obd->u.filter.fo_ctxt);
-
- 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));
- }
-
- 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);
- 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 %Ld\n",
- (unsigned long long)o->ioo_id);
- dput(dentry);
- GOTO(out_clean, rc = -ENOENT);
- }
-
- for (j = 0; j < o->ioo_bufcnt; j++, b++, r++) {
- unsigned long index = b->offset >> PAGE_SHIFT;
- struct page *page;
-
- if (j == 0)
- r->dentry = dentry;
- else
- r->dentry = dget(dentry);
-
- if (cmd & OBD_BRW_WRITE)
- page = filter_get_page_write(inode, index, r);
- else
- page = lustre_get_page_read(inode, index);
-
- if (IS_ERR(page)) {
- dput(dentry);
- GOTO(out_clean, rc = PTR_ERR(page));
- }
-
- r->addr = page_address(page);
- r->offset = b->offset;
- r->page = page;
- r->len = PAGE_SIZE;
- }
- }
-
-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);
- RETURN(rc);
-out_clean:
- while (r-- > res) {
- dput(r->dentry);
- if (cmd & OBD_BRW_WRITE)
- filter_commit_write(r->page, 0, PAGE_SIZE, rc);
- else
- lustre_put_page(r->page);
- }
- 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);
- }
-
- memcpy(page_address(lpage), kmap(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:
- kunmap(lnb->page);
- __free_pages(lnb->page, 0);
- dput(lnb->dentry);
-
- 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 = obj;
- struct niobuf_local *r = res;
- 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);
- journal_save = current->journal_info;
- if (journal_save)
- CERROR("Existing handle %p???\n", journal_save);
- current->journal_info = private;
- for (i = 0; i < objcount; i++, obj++) {
- 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 = 1;
- continue;
- }
-
- if (cmd & OBD_BRW_WRITE) {
- int err = filter_commit_write(page, 0,
- PAGE_SIZE, 0);
-
- if (!rc)
- rc = err;
- } else
- lustre_put_page(page);
-
- CDEBUG(D_INODE,
- "put inode %p (%ld), count = %d, nlink = %d\n",
- page->mapping->host,
- page->mapping->host->i_ino,
- atomic_read(&page->mapping->host->i_count) - 1,
- page->mapping->host->i_nlink);
- dput(r->dentry);
- }
- }
- if (!found_locked)
- goto out_ctxt;
-
- for (i = 0; i < objcount; i++, obj++) {
- 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);
- if (!rc)
- rc = err;
- }
- }
-
-out_ctxt:
- current->journal_info = journal_save;
- pop_ctxt(&saved);
- RETURN(0);
-}
-
-static int filter_statfs(struct lustre_handle *conn, struct statfs *statfs)
-{
- struct obd_device *obd = class_conn2obd(conn);
-
- ENTRY;
- RETURN(vfs_statfs(obd->u.filter.fo_sb, statfs));
-}
-
-static int filter_get_info(struct lustre_handle *conn, obd_count keylen,
- void *key, obd_count *vallen, void **val)
-{
- struct obd_device *obd;
- struct obd_export * export;
- ENTRY;
-
- if (!(export = class_conn2export(conn))) {
- CDEBUG(D_IOCTL, "invalid client %Lx\n", conn->addr);
- RETURN(-EINVAL);
- }
-
- obd = class_conn2obd(conn);
-
- 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.lmd_object_id = src->o_id;
- dstmd.lmd_object_id = dst->o_id;
-
- ENTRY;
- CDEBUG(D_INFO, "src: ino %Ld blocks %Ld, size %Ld, dst: ino %Ld\n",
- (unsigned long long)src->o_id, (unsigned long long)src->o_blocks,
- (unsigned long long)src->o_size, (unsigned long long)dst->o_id);
- page = alloc_page(GFP_USER);
- if (page == NULL)
- RETURN(-ENOMEM);
-
- while (TryLockPage(page))
- ___wait_on_page(page);
-
- /* 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 io_cb_data *cbd = ll_init_cb();
-
- if (!cbd) {
- err = -ENOMEM;
- EXIT;
- break;
- }
-
- pg.pg = page;
- pg.count = PAGE_SIZE;
- pg.off = (page->index) << PAGE_SHIFT;
- pg.flag = 0;
-
- page->index = index;
- err = obd_brw(OBD_BRW_READ, src_conn, &srcmd, 1, &pg,
- ll_sync_io_cb, cbd);
-
- if ( err ) {
- EXIT;
- break;
- }
-
- cbd = ll_init_cb();
- if (!cbd) {
- err = -ENOMEM;
- EXIT;
- break;
- }
- pg.flag = OBD_BRW_CREATE;
- CDEBUG(D_INFO, "Read page %ld ...\n", page->index);
-
- err = obd_brw(OBD_BRW_WRITE, dst_conn, &dstmd, 1, &pg,
- ll_sync_io_cb, cbd);
-
- /* 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);
- UnlockPage(page);
- __free_page(page);
-
- RETURN(err);
-}
-
-
-static struct obd_ops filter_obd_ops = {
- 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");
- return class_register_type(&filter_obd_ops, OBD_FILTER_DEVICENAME);
-}
-
-static void __exit obdfilter_exit(void)
-{
- class_unregister_type(OBD_FILTER_DEVICENAME);
-}
-
-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
-.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 = obdfs
-modulefs_DATA = obdfs.o
-EXTRA_PROGRAMS = obdfs
-obdfs_SOURCES = rw.c file.c dir.c sysctl.c super.c namei.c symlink.c
-
-include $(top_srcdir)/Rules
+++ /dev/null
-OBDFS - v 0.001
-
-This version can mount, list and set the attributes of the root
-directory.
-
-1. configure the obd to use /dev/obd with a scratch file system
-
-2. make
-
-3. insmod obdfs
-
-4. mount -t obdfs -o device=/dev/obd0 /dev/obd0 /mnt/obd
-
-To verify: type mount (output:
-/dev/obd on /mnt/obd type obdfs (rw))
-
-5. ls -ld /mnt/obd
-
-6. chmod 711 /mnt/obd, ls -ld /mnt/obd
-
-7. chown disk /mnt/obd, ls -ld /mnt/obd
-
+++ /dev/null
-/*
- * linux/fs/ext2/dir.c
- *
- * 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
- *
- * 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
- */
-
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/pagemap.h>
-
-#define DEBUG_SUBSYSTEM S_OBDFS
-
-#include <linux/obd_support.h>
-#include <linux/locks.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)
-
-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;
-}
-
-/*
- * 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;
- return PAGE_SIZE;
-}
-
-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;
-}
-
-static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to)
-{
- struct inode *dir = page->mapping->host;
- int err = 0;
- dir->i_version = ++event;
- 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))
- 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);
- }
- 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",
- 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);
-}
-
-static struct page * ext2_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 (!Page_Uptodate(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 obdfs_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
-new_obdfs_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);
-
- if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))
- goto done;
-
- types = ext2_filetype_table;
-
- for ( ; n < npages; n++, offset = 0) {
- char *kaddr, *limit;
- ext2_dirent *de;
- struct page *page = ext2_get_page(inode, n);
-
- 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;
- }
- }
- 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 = ext2_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 = ext2_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;
-}
-
-ino_t obdfs_inode_by_name(struct inode * dir, struct dentry *dentry, int *type)
-{
- ino_t 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 = obdfs_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);
- UnlockPage(page);
- ext2_put_page(page);
-}
-
-/*
- * Parent is locked.
- */
-int ext2_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 = ext2_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
- // obdfs_change_inode(dir);
- /* OFFSET_CACHE */
-out_unlock:
- UnlockPage(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);
- UnlockPage(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;
- err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size);
- if (err)
- goto fail;
-
- base = page_address(page);
-
- 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:
- UnlockPage(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 = ext2_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 obdfs_dir_operations = {
- read: generic_read_dir,
- readdir: new_obdfs_readdir
-};
+++ /dev/null
-/*
- * 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)
- */
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/smp_lock.h>
-
-#define DEBUG_SUBSYSTEM S_OBDFS
-
-#include <linux/obd_support.h>
-#include <linux/obdfs.h>
-
-extern int obdfs_setattr(struct dentry *de, struct iattr *attr);
-void obdfs_change_inode(struct inode *inode);
-
-static inline void obdfs_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
- //obdfs_change_inode(inode);
- }
-}
-
-/*
- * Write to a file (through the page cache).
- */
-static ssize_t
-obdfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- ssize_t retval;
- CDEBUG(D_INFO, "Writing inode %ld, %ld bytes, offset %Ld\n",
- file->f_dentry->d_inode->i_ino, (long)count, *ppos);
-
- retval = generic_file_write(file, buf, count, ppos);
- CDEBUG(D_INFO, "Wrote %ld\n", (long)retval);
-
- /* update mtime/ctime/atime here, NOT size */
- if (retval > 0) {
- struct iattr attr;
- attr.ia_valid = ATTR_MTIME | ATTR_CTIME | ATTR_ATIME;
- attr.ia_mtime = attr.ia_ctime = attr.ia_atime =
- CURRENT_TIME;
- obdfs_setattr(file->f_dentry, &attr);
- }
- EXIT;
- return retval;
-}
-
-
-/* XXX this does not need to do anything for data, it _does_ need to
- call setattr */
-int obdfs_fsync(struct file *file, struct dentry *dentry, int data)
-{
- return 0;
-}
-
-struct file_operations obdfs_file_operations = {
- read: generic_file_read,
- write: obdfs_file_write,
- mmap: generic_file_mmap,
- fsync: NULL
-};
-
-
-struct inode_operations obdfs_file_inode_operations = {
- truncate: obdfs_truncate,
- setattr: obdfs_setattr
-};
-
+++ /dev/null
-/*
- * OBDFS Super operations - also used for Lustre file system
- *
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- * Copryright (C) 1999 Stelias Computing Inc. <braam@stelias.com>
- * Copryright (C) 1999 Seagate Technology Inc.
- *
- */
-#define __NO_VERSION__
-#include <linux/fs.h>
-#include <linux/locks.h>
-#include <linux/swap.h>
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/obdfs.h>
-
-
-/* XXX temporary until the real function is available from kernel
- * XXX set this to memory size in pages for max page cache size
- */
-#define nr_free_buffer_pages() 32768
-
-/* Defines for page buf daemon */
-struct pupd_prm {
- int nfract; /* Percentage of buffer cache dirty to
- activate bdflush */
- int ndirty; /* Maximum number of dirty blocks to write out per
- wake-cycle */
- int nrefill; /* Number of clean buffers to try to obtain
- each time we call refill */
- int nref_dirt; /* Dirty buffer threshold for activating bdflush
- when trying to refill buffers. */
- int interval; /* jiffies delay between pupdate flushes */
- int age_buffer; /* Time for normal buffer to age before we flush it */
- int age_super; /* Time for superblock to age before we flush it */
-};
-
-
-static struct pupdated {
- int active;
- wait_queue_head_t waitq;
- struct timer_list timer;
- struct pupd_prm parms;
-} pupdated = {
- active: -1,
- parms: {40, 1024, 64, 256, 1*HZ, 30*HZ, 5*HZ }
-};
-
-
-/* Called with the superblock list lock held */
-static int obdfs_enqueue_pages(struct inode *inode, struct obdo **obdo,
- int nr_slots, struct page **pages, char **bufs,
- obd_size *counts, obd_off *offsets,
- obd_flag *flag, unsigned long check_time)
-{
- struct list_head *page_list = obdfs_iplist(inode);
- struct list_head *tmp;
- int num = 0;
-
- ENTRY;
-
- tmp = page_list;
- /* Traverse list in reverse order, so we do FIFO, not LIFO order */
- while ( (tmp = tmp->prev) != page_list && num < nr_slots ) {
- struct obdfs_pgrq *req;
- struct page *page;
-
- req = list_entry(tmp, struct obdfs_pgrq, rq_plist);
- page = req->rq_page;
-
-
- if (req->rq_jiffies > check_time)
- break; /* pages are in chronological order */
-
- /* Only allocate the obdo if we will actually do I/O here */
- if ( !*obdo ) {
- OIDEBUG(inode);
- *obdo = obdo_fromid(IID(inode), inode->i_ino,
- OBD_MD_FLNOTOBD);
- if ( IS_ERR(*obdo) ) {
- int err = PTR_ERR(*obdo);
- *obdo = NULL;
-
- EXIT;
- return err;
- }
-
- /* FIXME revisit fromid & from_inode */
- obdfs_from_inode(*obdo, inode);
- *flag = OBD_BRW_CREATE;
- }
-
- /* Remove request from list before write to avoid conflict.
- * Note that obdfs_pgrq_del() also deletes the request.
- */
- obdfs_pgrq_del(req);
- if ( !page ) {
- CDEBUG(D_CACHE, "no page \n");
- continue;
- }
-
- bufs[num] = (char *)page_address(page);
- pages[num] = page;
- counts[num] = PAGE_SIZE;
- offsets[num] = ((obd_off)page->index) << PAGE_SHIFT;
- CDEBUG(D_INFO, "ENQ inode %ld, page %p addr %p to vector\n",
- inode->i_ino, page, (char *)page_address(page));
- num++;
- }
-
- if (!list_empty(page_list))
- CDEBUG(D_INFO, "inode %ld list not empty\n", inode->i_ino);
- CDEBUG(D_INFO, "added %d page(s) to vector\n", num);
-
- EXIT;
- return num;
-} /* obdfs_enqueue_pages */
-
-/* Dequeue cached pages for a dying inode without writing them to disk. */
-void obdfs_dequeue_pages(struct inode *inode)
-{
- struct list_head *tmp;
-
- ENTRY;
- obd_down(&obdfs_i2sbi(inode)->osi_list_mutex);
- tmp = obdfs_islist(inode);
- if ( list_empty(tmp) ) {
- CDEBUG(D_INFO, "no dirty pages for inode %ld\n", inode->i_ino);
- obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
- EXIT;
- return;
- }
-
- /* take it out of the super list */
- list_del(tmp);
- INIT_LIST_HEAD(obdfs_islist(inode));
-
- tmp = obdfs_iplist(inode);
- while ( (tmp = tmp->prev) != obdfs_iplist(inode) ) {
- struct obdfs_pgrq *req;
- struct page *page;
-
- req = list_entry(tmp, struct obdfs_pgrq, rq_plist);
- page = req->rq_page;
- /* take it out of the list and free */
- obdfs_pgrq_del(req);
- /* now put the page away */
- put_page(page);
- }
-
- obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
-
- /* decrement inode reference for page cache */
- atomic_dec(&inode->i_count);
- EXIT;
-}
-
-/* This value is not arbitrarily chosen. KIO_STATIC_PAGES from linux/iobuf.h */
-#define MAX_IOVEC (KIO_STATIC_PAGES - 1)
-
-/* Remove writeback requests for the superblock */
-int obdfs_flush_reqs(struct list_head *inode_list, unsigned long check_time)
-{
- struct list_head *tmp;
- unsigned long max_io, total_io = 0;
- obd_count num_io;
- obd_count num_obdos;
- struct inode *inodes[MAX_IOVEC]; /* write data back to these */
- struct page *pages[MAX_IOVEC]; /* call put_page on these */
- struct obdo *obdos[MAX_IOVEC];
- char *bufs[MAX_IOVEC];
- obd_size counts[MAX_IOVEC];
- obd_off offsets[MAX_IOVEC];
- obd_flag flags[MAX_IOVEC];
- obd_count bufs_per_obdo[MAX_IOVEC];
- int err = 0;
- struct obdfs_sb_info *sbi;
-
- ENTRY;
- if (!inode_list) {
- CDEBUG(D_INODE, "no list\n");
- EXIT;
- return 0;
- }
-
- sbi = list_entry(inode_list, struct obdfs_sb_info, osi_inodes);
-
- obd_down(&sbi->osi_list_mutex);
- if ( list_empty(inode_list) ) {
- CDEBUG(D_INFO, "list empty\n");
- obd_up(&sbi->osi_list_mutex);
- EXIT;
- return 0;
- }
-
- /* If we are forcing a write, write out all dirty pages */
- max_io = check_time == ~0UL ? 1<<31 : pupdated.parms.ndirty;
- CDEBUG(D_INFO, "max_io = %lu\n", max_io);
-
- /* Add each inode's dirty pages to a write vector, and write it.
- * Traverse list in reverse order, so we do FIFO, not LIFO order
- */
- again:
- tmp = inode_list;
- num_io = 0;
- num_obdos = 0;
- while ( (tmp = tmp->prev) != inode_list && total_io < max_io) {
- struct obdfs_inode_info *ii;
- struct inode *inode;
- int res;
-
- ii = list_entry(tmp, struct obdfs_inode_info, oi_inodes);
- inode = list_entry(ii, struct inode, u);
- inodes[num_obdos] = inode;
- obdos[num_obdos] = NULL;
- CDEBUG(D_INFO, "checking inode %ld pages\n", inode->i_ino);
-
- /* Make sure we reference "inode" and not "inodes[num_obdos]",
- * as num_obdos will change after the loop is run.
- */
- if (!list_empty(obdfs_iplist(inode))) {
- res = obdfs_enqueue_pages(inode, &obdos[num_obdos],
- MAX_IOVEC - num_io,
- &pages[num_io], &bufs[num_io],
- &counts[num_io],
- &offsets[num_io],
- &flags[num_obdos],
- check_time);
- CDEBUG(D_INFO, "FLUSH inode %ld, pages flushed: %d\n",
- inode->i_ino, res);
- if ( res < 0 ) {
- CDEBUG(D_INODE,
- "fatal: unable to enqueue inode %ld (err %d)\n",
- inode->i_ino, res);
- /* XXX Move bad inode to end of list so we can
- * continue with flushing list. This is a
- * temporary measure to avoid machine lockups.
- * Maybe if we have -ENOENT, simply discard.
- */
- list_del(tmp);
- list_add(tmp, inode_list);
- err = res;
- EXIT;
- goto BREAK;
- }
- if (res == 0)
- continue;
-
- num_io += res;
- total_io += res;
- bufs_per_obdo[num_obdos] = res;
- num_obdos++;
-
- if ( num_io == MAX_IOVEC ) {
- obd_up(&sbi->osi_list_mutex);
- err = obdfs_do_vec_wr(inodes, num_io, num_obdos,
- obdos, bufs_per_obdo,
- pages, bufs, counts,
- offsets, flags);
- if ( err ) {
- CDEBUG(D_INODE,
- "fatal: do_vec_wr err=%d\n",
- err);
- EXIT;
- goto ERR;
- }
- obd_down(&sbi->osi_list_mutex);
- goto again;
- }
- }
- }
-
-BREAK:
- obd_up(&sbi->osi_list_mutex);
-
- /* flush any remaining I/Os */
- if ( num_io ) {
- err = obdfs_do_vec_wr(inodes, num_io, num_obdos, obdos,
- bufs_per_obdo, pages, bufs, counts,
- offsets, flags);
- if (err)
- CDEBUG(D_INODE, "fatal: unable to do vec_wr (err %d)\n", err);
- num_io = 0;
- num_obdos = 0;
- }
-
- /* Remove inode from superblock dirty list when no more pages.
- * Make sure we don't point at the current inode with tmp
- * when we re-init the list on the inode, or we will loop.
- */
- obd_down(&sbi->osi_list_mutex);
- tmp = inode_list;
- while ( (tmp = tmp->prev) != inode_list ) {
- struct obdfs_inode_info *ii;
- struct inode *inode;
-
- ii = list_entry(tmp, struct obdfs_inode_info, oi_inodes);
- inode = list_entry(ii, struct inode, u);
- CDEBUG(D_INFO, "checking inode %ld empty\n", inode->i_ino);
- if (list_empty(obdfs_iplist(inode))) {
- CDEBUG(D_INFO, "remove inode %ld from dirty list\n",
- inode->i_ino);
- tmp = tmp->next;
- list_del(obdfs_islist(inode));
- /* decrement inode reference for page cache */
- atomic_dec(&inode->i_count);
- INIT_LIST_HEAD(obdfs_islist(inode));
- }
- }
- obd_up(&sbi->osi_list_mutex);
-
- CDEBUG(D_INFO, "flushed %ld pages in total\n", total_io);
- EXIT;
-ERR:
- return err ? err : total_io;
-} /* obdfs_flush_reqs */
-
-
-/* Walk all of the superblocks and write out blocks which are too old.
- * Return the maximum number of blocks written for a single filesystem.
- */
-int obdfs_flush_dirty_pages(unsigned long check_time)
-{
- struct list_head *sl;
- int max = 0;
-
- /* ENTRY; */
- sl = &obdfs_super_list;
- while ( (sl = sl->prev) != &obdfs_super_list ) {
- struct obdfs_sb_info *sbi =
- list_entry(sl, struct obdfs_sb_info, osi_list);
- int ret;
-
- /* walk write requests here, use the sb, check the time */
- ret = obdfs_flush_reqs(&sbi->osi_inodes, check_time);
- /* XXX handle error? What to do with it? */
-
- max = ret > max ? ret : max;
- }
- if (max) { EXIT; }
- return max;
-} /* obdfs_flush_dirty_pages */
-
-
-static void pupdate_wakeup(unsigned long l)
-{
- wake_up(&pupdated.waitq);
-}
-
-
-static int pupdate(void *unused)
-{
- u_long flags;
- int interval = pupdated.parms.interval;
- long age = pupdated.parms.age_buffer;
- int wrote = 0;
-
- if (pupdated.active >= 0) {
- CDEBUG(D_CACHE, "attempted to run multiple pupdates\n");
- return 1;
- }
-
- init_timer(&pupdated.timer);
- init_waitqueue_head(&pupdated.waitq);
- pupdated.timer.function = pupdate_wakeup;
-
- exit_files(current);
- exit_mm(current);
- daemonize();
-
- current->session = 1;
- current->pgrp = 1;
- strcpy(current->comm, "pupdated");
-
- CDEBUG(D_CACHE, "pupdated activated...\n");
- pupdated.active = 1;
-
- spin_lock_irqsave(¤t->sigmask_lock, flags);
- flush_signals(current);
- sigfillset(¤t->blocked);
- recalc_sigpending(current);
- spin_unlock_irqrestore(¤t->sigmask_lock, flags);
-
- do {
- long dirty_limit;
-
- /* update interval */
- if (pupdated.active == 1 && interval) {
- mod_timer(&pupdated.timer, jiffies + interval);
- interruptible_sleep_on(&pupdated.waitq);
- }
- if (pupdated.active == 0) {
- del_timer(&pupdated.timer);
- /* If stopped, we flush one last time... */
- }
-
- /* asynchronous setattr etc for the future ...
- obdfs_flush_dirty_inodes(jiffies - pupdated.parms.age_super);
- */
- dirty_limit = nr_free_buffer_pages() * pupdated.parms.nfract / 100;
-
- if (obdfs_cache_count > dirty_limit) {
- interval = 0;
- if (wrote < pupdated.parms.ndirty)
- age >>= 1;
- if (wrote)
- CDEBUG(D_CACHE, "wrote %d, age %ld, interval %d\n",
- wrote, age, interval);
- } else {
- if (wrote < pupdated.parms.ndirty >> 1 &&
- obdfs_cache_count < dirty_limit / 2) {
- interval = pupdated.parms.interval;
- age = pupdated.parms.age_buffer;
- if (wrote)
- CDEBUG(D_INFO,
- "wrote %d, age %ld, interval %d\n",
- wrote, age, interval);
- } else if (obdfs_cache_count > dirty_limit / 2) {
- interval >>= 1;
- if (wrote < pupdated.parms.ndirty)
- age >>= 1;
- if (wrote)
- CDEBUG(D_CACHE,
- "wrote %d, age %ld, interval %d\n",
- wrote, age, interval);
- }
- }
-
- wrote = obdfs_flush_dirty_pages(jiffies - age);
- if (wrote) {
- CDEBUG(D_CACHE,
- "dirty_limit %ld, cache_count %ld, wrote %d\n",
- dirty_limit, obdfs_cache_count, wrote);
- run_task_queue(&tq_disk);
- }
- } while (pupdated.active == 1);
-
- CDEBUG(D_CACHE, "pupdated stopped...\n");
- pupdated.active = -1;
- wake_up(&pupdated.waitq);
- return 0;
-}
-
-
-int obdfs_flushd_init(void)
-{
- /*
- kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- */
- kernel_thread(pupdate, NULL, 0);
- CDEBUG(D_PSDEV, "flushd inited\n");
- return 0;
-}
-
-int obdfs_flushd_cleanup(void)
-{
- ENTRY;
-
- /* Shut down pupdated. */
- if (pupdated.active > 0) {
- CDEBUG(D_CACHE, "inform pupdated\n");
- pupdated.active = 0;
- wake_up(&pupdated.waitq);
-
- CDEBUG(D_CACHE, "wait for pupdated\n");
- while (pupdated.active == 0) {
- interruptible_sleep_on(&pupdated.waitq);
- }
- CDEBUG(D_CACHE, "done waiting for pupdated\n");
- }
-
- EXIT;
- return 0;
-}
+++ /dev/null
-/*
- * linux/fs/obdfs/namei.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/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/locks.h>
-#include <linux/quotaops.h>
-
-#define DEBUG_SUBSYSTEM S_OBDFS
-
-#include <linux/obdfs.h>
-#include <linux/lustre_lite.h>
-extern struct address_space_operations obdfs_aops;
-
-/* from super.c */
-extern void obdfs_change_inode(struct inode *inode);
-extern int obdfs_setattr(struct dentry *de, struct iattr *attr);
-
-/* from dir.c */
-extern int ext2_add_link (struct dentry *dentry, struct inode *inode);
-obd_id obdfs_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++;
- obdfs_change_inode(inode);
-}
-
-/* postpone the disk update until the inode really goes away */
-static inline void ext2_dec_count(struct inode *inode)
-{
- inode->i_nlink--;
- if (inode->i_nlink > 0)
- obdfs_change_inode(inode);
-}
-
-static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
-{
- int err;
- err = ext2_add_link(dentry, inode);
- if (!err) {
- d_instantiate(dentry, inode);
- return 0;
- }
- ext2_dec_count(inode);
- iput(inode);
- return err;
-}
-
-/* methods */
-static struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry)
-{
- struct obdo *oa;
- struct inode * inode = NULL;
- int type;
- obd_id ino;
-
- ENTRY;
- if (dentry->d_name.len > EXT2_NAME_LEN)
- return ERR_PTR(-ENAMETOOLONG);
-
- ino = obdfs_inode_by_name(dir, dentry, &type);
- if (!ino)
- goto negative;
-
- oa = obdo_fromid(IID(dir), ino, type,
- (__u32)(OBD_MD_FLNOTOBD | OBD_MD_FLBLOCKS));
- if ( IS_ERR(oa) ) {
- CERROR("obdo_fromid failed\n");
- EXIT;
- return ERR_PTR(-EACCES);
- }
-
- inode = iget4(dir->i_sb, (ino_t)ino, NULL, oa);
- obdo_free(oa);
-
- if (!inode)
- return ERR_PTR(-EACCES);
-
- negative:
- d_add(dentry, inode);
- return NULL;
-}
-
-
-/*
- * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
- *
- * `len <= EXT2_NAME_LEN' is guaranteed by caller.
- * `de != NULL' is 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);
-}
-
-static struct inode *obdfs_new_inode(struct inode *dir, int mode)
-{
- struct obdo *oa;
- struct inode *inode;
- int err;
-
- ENTRY;
- oa = obdo_alloc();
- if (!oa) {
- EXIT;
- return ERR_PTR(-ENOMEM);
- }
-
- /* Send a hint to the create method on the type of file to create */
- oa->o_mode = mode;
- oa->o_valid |= OBD_MD_FLMODE;
- CDEBUG(D_INODE, "\n");
- err = obd_create(IID(dir), oa, NULL);
- CDEBUG(D_INODE, "\n");
-
- if ( err ) {
- CERROR("new_inode - fatal: err %d\n", err);
- obdo_free(oa);
- EXIT;
- return ERR_PTR(err);
- }
- CDEBUG(D_INODE, "obdo mode %o\n", oa->o_mode);
-
- inode = iget4(dir->i_sb, (ino_t)oa->o_id, NULL, oa);
- CDEBUG(D_INODE, "\n");
-
- if (!inode) {
- CERROR("new_inode -fatal: %ld\n", (long)oa->o_id);
- obd_destroy(IID(dir), oa, NULL);
- obdo_free(oa);
- EXIT;
- return ERR_PTR(-EIO);
- }
- obdo_free(oa);
-
- if (!list_empty(&inode->i_dentry)) {
- CERROR("new_inode -fatal: aliases %ld, ct %d lnk %d\n",
- (long)oa->o_id,
- atomic_read(&inode->i_count),
- inode->i_nlink);
- obd_destroy(IID(dir), oa, NULL);
- iput(inode);
- EXIT;
- return ERR_PTR(-EIO);
- }
-
- EXIT;
- return inode;
-} /* obdfs_new_inode */
-
-
-/*
- * 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.
- *
- * If the create succeeds, we fill in the inode information
- * with d_instantiate().
- */
-static int obdfs_create (struct inode * dir, struct dentry * dentry, int mode)
-{
- struct inode * inode = obdfs_new_inode (dir, mode);
- int err = PTR_ERR(inode);
- if (!IS_ERR(inode)) {
- inode->i_op = &obdfs_file_inode_operations;
- inode->i_fop = &obdfs_file_operations;
- inode->i_mapping->a_ops = &obdfs_aops;
- err = ext2_add_nondir(dentry, inode);
- }
- return err;
-} /* obdfs_create */
-
-
-static int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
-{
- struct inode * inode = obdfs_new_inode (dir, mode);
- int err = PTR_ERR(inode);
- if (!IS_ERR(inode)) {
- init_special_inode(inode, mode, rdev);
- obdfs_change_inode(inode);
- err = ext2_add_nondir(dentry, inode);
- }
- return err;
-}
-
-static int obdfs_symlink (struct inode * dir, struct dentry * dentry,
- const char * symname)
-{
- struct super_block * sb = dir->i_sb;
- int err = -ENAMETOOLONG;
- unsigned l = strlen(symname)+1;
- struct inode * inode;
- struct obdfs_inode_info *oinfo;
-
- if (l > sb->s_blocksize)
- goto out;
-
- inode = obdfs_new_inode (dir, S_IFLNK | S_IRWXUGO);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out;
-
- oinfo = obdfs_i2info(inode);
- if (l >= sizeof(oinfo->oi_inline)) {
- /* slow symlink */
- inode->i_op = &page_symlink_inode_operations;
- inode->i_mapping->a_ops = &obdfs_aops;
- err = block_symlink(inode, symname, l);
- if (err)
- goto out_fail;
- } else {
- /* fast symlink */
- inode->i_op = &obdfs_fast_symlink_inode_operations;
- memcpy(oinfo->oi_inline, symname, l);
- inode->i_size = l-1;
- }
- obdfs_change_inode(inode);
-
- err = ext2_add_nondir(dentry, inode);
-out:
- return err;
-
-out_fail:
- ext2_dec_count(inode);
- iput (inode);
- goto out;
-}
-
-
-
-static int obdfs_link (struct dentry * old_dentry, struct inode * dir,
- struct dentry *dentry)
-{
- struct inode *inode = old_dentry->d_inode;
-
- if (S_ISDIR(inode->i_mode))
- return -EPERM;
-
- if (inode->i_nlink >= EXT2_LINK_MAX)
- return -EMLINK;
-
- inode->i_ctime = CURRENT_TIME;
- ext2_inc_count(inode);
- atomic_inc(&inode->i_count);
-
- return ext2_add_nondir(dentry, inode);
-}
-
-
-static int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
-{
- struct inode * inode;
- int err = -EMLINK;
- ENTRY;
-
- if (dir->i_nlink >= EXT2_LINK_MAX)
- goto out;
-
- ext2_inc_count(dir);
-
- inode = obdfs_new_inode (dir, S_IFDIR | mode);
- err = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto out_dir;
-
- inode->i_op = &obdfs_dir_inode_operations;
- inode->i_fop = &obdfs_dir_operations;
- inode->i_mapping->a_ops = &obdfs_aops;
-
- ext2_inc_count(inode);
-
- err = ext2_make_empty(inode, dir);
- if (err)
- goto out_fail;
-
- err = ext2_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 obdfs_unlink(struct inode * dir, struct dentry *dentry)
-{
- struct inode * inode = dentry->d_inode;
- struct ext2_dir_entry_2 * de;
- struct page * page;
- int err = -ENOENT;
-
- de = ext2_find_entry (dir, dentry, &page);
- if (!de)
- goto out;
-
- err = ext2_delete_entry (de, page);
- if (err)
- goto out;
-
- inode->i_ctime = dir->i_ctime;
- ext2_dec_count(inode);
- err = 0;
-out:
- return err;
-}
-
-
-static int obdfs_rmdir (struct inode * dir, struct dentry *dentry)
-{
- struct inode * inode = dentry->d_inode;
- int err = -ENOTEMPTY;
-
- if (ext2_empty_dir(inode)) {
- err = obdfs_unlink(dir, dentry);
- if (!err) {
- inode->i_size = 0;
- ext2_dec_count(inode);
- ext2_dec_count(dir);
- }
- }
- return err;
-}
-
-static int obdfs_rename (struct inode * old_dir, struct dentry * old_dentry,
- struct inode * new_dir, struct dentry * new_dentry )
-{
- struct inode * old_inode = old_dentry->d_inode;
- struct inode * new_inode = new_dentry->d_inode;
- struct page * dir_page = NULL;
- struct ext2_dir_entry_2 * dir_de = NULL;
- struct page * old_page;
- struct ext2_dir_entry_2 * old_de;
- int err = -ENOENT;
-
- 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 (new_inode) {
- struct page *new_page;
- struct ext2_dir_entry_2 *new_de;
-
- err = -ENOTEMPTY;
- if (dir_de && !ext2_empty_dir (new_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);
- new_inode->i_ctime = CURRENT_TIME;
- if (dir_de)
- new_inode->i_nlink--;
- ext2_dec_count(new_inode);
- } else {
- if (dir_de) {
- err = -EMLINK;
- if (new_dir->i_nlink >= EXT2_LINK_MAX)
- goto out_dir;
- }
- ext2_inc_count(old_inode);
- err = ext2_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 obdfs_dir_inode_operations = {
- create: obdfs_create,
- lookup: obdfs_lookup,
- link: obdfs_link,
- unlink: obdfs_unlink,
- symlink: obdfs_symlink,
- mkdir: obdfs_mkdir,
- rmdir: obdfs_rmdir,
- mknod: obdfs_mknod,
- rename: obdfs_rename,
- setattr: obdfs_setattr
-};
+++ /dev/null
-/*
- * OBDFS Super operations
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
- * Copryright (C) 1999 Stelias Computing Inc,
- * (author Peter J. Braam <braam@stelias.com>)
- * Copryright (C) 1999 Seagate Technology Inc.
-*/
-
-
-#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/locks.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 <linux/vmalloc.h>
-#include <asm/segment.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/smp_lock.h>
-
-#define DEBUG_SUBSYSTEM S_OBDFS
-
-#include <linux/obd_support.h>
-#include <linux/obd_ext2.h>
-#include <linux/obdfs.h>
-
-void obdfs_change_inode(struct inode *inode);
-
-static int cache_writes = 0;
-
-
-/* page cache support stuff */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
-/*
- * Add a page to the dirty page list.
- */
-void __set_page_dirty(struct page *page)
-{
- struct address_space *mapping;
- spinlock_t *pg_lock;
-
- pg_lock = PAGECACHE_LOCK(page);
- spin_lock(pg_lock);
-
- mapping = page->mapping;
- spin_lock(&mapping->page_lock);
-
- list_del(&page->list);
- list_add(&page->list, &mapping->dirty_pages);
-
- spin_unlock(&mapping->page_lock);
- spin_unlock(pg_lock);
-
- if (mapping->host)
- mark_inode_dirty_pages(mapping->host);
-}
-/*
- * Remove page from dirty list
- */
-void __set_page_clean(struct page *page)
-{
- struct address_space *mapping = page->mapping;
- struct inode *inode;
-
- if (!mapping)
- return;
-
- 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;
- }
- EXIT;
-}
-
-#else
-/*
- * Add a page to the dirty page list.
- */
-void set_page_dirty(struct page *page)
-{
- if (!test_and_set_bit(PG_dirty, &page->flags)) {
- struct address_space *mapping = page->mapping;
-
- if (mapping) {
- spin_lock(&pagecache_lock);
- list_del(&page->list);
- list_add(&page->list, &mapping->dirty_pages);
- spin_unlock(&pagecache_lock);
-
- if (mapping->host)
- mark_inode_dirty_pages(mapping->host);
- }
- }
-}
-/*
- * Remove page from dirty list
- */
-void __set_page_clean(struct page *page)
-{
- struct address_space *mapping = page->mapping;
- struct inode *inode;
-
- if (!mapping)
- return;
-
- spin_lock(&pagecache_lock);
- 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;
- }
- spin_unlock(&pagecache_lock);
- EXIT;
-}
-
-#endif
-
-
-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 -- object attr will be updated too */
-static int obdfs_brw(int rw, struct inode *inode2,
- struct page *page, int create)
-{
- struct inode *inode = page->mapping->host;
- struct ll_inode_info *lii = ll_i2info(inode);
- obd_size count = PAGE_SIZE;
- obd_off offset = ((obd_off)page->index) << PAGE_SHIFT;
- obd_flag flags = create ? OBD_BRW_CREATE : 0;
- int err;
-
- ENTRY;
-
- err = obd_brw(rw == WRITE ? OBD_BRW_WRITE : OBD_BRW_READ, IID(inode),
- md, 1, &page, &count, &offset,
- &flags, NULL);
- //if ( !err )
- // obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */
-
- obdo_free(oa);
- EXIT;
- return err;
-} /* obdfs_brw */
-
-extern void set_page_clean(struct page *);
-
-/* SYNCHRONOUS I/O to object storage for an inode -- object attr will be updated too */
-static int obdfs_commit_page(struct page *page, int create, int from, int to)
-{
- struct inode *inode = page->mapping->host;
- obd_count num_obdo = 1;
- obd_count bufs_per_obdo = 1;
- struct obdo *oa;
- obd_size count = to;
- obd_off offset = (((obd_off)page->index) << PAGE_SHIFT);
- obd_flag flags = create ? OBD_BRW_CREATE : 0;
- int err;
-
- ENTRY;
-
- CDEBUG(D_INODE, "commit_page writing (at %d) to %d, count %Ld\n",
- from, to, (unsigned long long)count);
-
- err = obd_brw(OBD_BRW_WRITE, IID(inode), md, 1,
- &page, &count, &offset, &flags, NULL);
- if ( !err ) {
- SetPageUptodate(page);
- set_page_clean(page);
- }
-
- //if ( !err )
- // obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */
-
- obdo_free(oa);
- EXIT;
- return err;
-} /* obdfs_brw */
-
-/* returns the page unlocked, but with a reference */
-int obdfs_writepage(struct page *page)
-{
- int rc;
- struct inode *inode = page->mapping->host;
- ENTRY;
- CERROR("---> writepage called ino %ld!\n", inode->i_ino);
- LBUG();
- rc = obdfs_brw(OBD_BRW_WRITE, inode, page, 1);
- if ( !rc ) {
- set_page_clean(page);
- } else {
- CDEBUG(D_INODE, "--> GRR %d\n", rc);
- }
- EXIT;
- return rc;
-}
-
-
-void write_inode_pages(struct inode *inode)
-{
- struct list_head *tmp = &inode->i_mapping->dirty_pages;
-
- while ( (tmp = tmp->next) != &inode->i_mapping->dirty_pages) {
- struct page *page;
- page = list_entry(tmp, struct page, list);
- obdfs_writepage(page);
- }
-}
-
-
-/* returns the page unlocked, but with a reference */
-int obdfs_readpage(struct file *file, struct page *page)
-{
- struct inode *inode = page->mapping->host;
- int rc;
-
- 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;
- }
-
- if (Page_Uptodate(page)) {
- EXIT;
- goto readpage_out;
- }
-
- rc = obdfs_brw(OBD_BRW_READ, inode, page, 0);
- if ( rc ) {
- EXIT;
- return rc;
- }
-
- readpage_out:
- SetPageUptodate(page);
- UnlockPage(page);
- EXIT;
- return 0;
-} /* obdfs_readpage */
-
-int obdfs_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;
- ENTRY;
-
- kmap(page);
- if (Page_Uptodate(page)) {
- EXIT;
- goto prepare_done;
- }
-
- if ( (from <= offset) && (to >= offset + PAGE_SIZE) ) {
- EXIT;
- return 0;
- }
-
- rc = obdfs_brw(OBD_BRW_READ, inode, page, 0);
- if (!rc)
- SetPageUptodate(page);
-
- prepare_done:
- set_page_dirty(page);
- //SetPageDirty(page);
- EXIT;
- return rc;
-}
-
-
-#if 0
-
-
-
-static kmem_cache_t *obdfs_pgrq_cachep = NULL;
-
-int obdfs_init_pgrqcache(void)
-{
- ENTRY;
- if (obdfs_pgrq_cachep == NULL) {
- CDEBUG(D_CACHE, "allocating obdfs_pgrq_cache\n");
- obdfs_pgrq_cachep = kmem_cache_create("obdfs_pgrq",
- sizeof(struct obdfs_pgrq),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (obdfs_pgrq_cachep == NULL) {
- EXIT;
- return -ENOMEM;
- } else {
- CDEBUG(D_CACHE, "allocated cache at %p\n",
- obdfs_pgrq_cachep);
- }
- } else {
- CDEBUG(D_CACHE, "using existing cache at %p\n",
- obdfs_pgrq_cachep);
- }
- EXIT;
- return 0;
-} /* obdfs_init_wreqcache */
-
-inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq)
-{
- --obdfs_cache_count;
- CDEBUG(D_INFO, "deleting page %p from list [count %ld]\n",
- pgrq->rq_page, obdfs_cache_count);
- list_del(&pgrq->rq_plist);
- OBDClearCachePage(pgrq->rq_page);
- kmem_cache_free(obdfs_pgrq_cachep, pgrq);
-}
-
-void obdfs_cleanup_pgrqcache(void)
-{
- ENTRY;
- if (obdfs_pgrq_cachep != NULL) {
- CDEBUG(D_CACHE, "destroying obdfs_pgrqcache at %p, count %ld\n",
- obdfs_pgrq_cachep, obdfs_cache_count);
- if (kmem_cache_destroy(obdfs_pgrq_cachep))
- CERROR("unable to free all of cache\n");
- obdfs_pgrq_cachep = NULL;
- } else
- CERROR("called with NULL pointer\n");
-
- EXIT;
-} /* obdfs_cleanup_wreqcache */
-
-
-/* called with the list lock held */
-static struct page *obdfs_find_page_index(struct inode *inode,
- unsigned long index)
-{
- struct list_head *page_list = obdfs_iplist(inode);
- struct list_head *tmp;
- struct page *page;
-
- ENTRY;
-
- CDEBUG(D_INFO, "looking for inode %ld pageindex %ld\n",
- inode->i_ino, index);
- OIDEBUG(inode);
-
- if (list_empty(page_list)) {
- EXIT;
- return NULL;
- }
- tmp = page_list;
- while ( (tmp = tmp->next) != page_list ) {
- struct obdfs_pgrq *pgrq;
-
- pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist);
- page = pgrq->rq_page;
- if (index == page->index) {
- CDEBUG(D_INFO,
- "INDEX SEARCH found page %p, index %ld\n",
- page, index);
- EXIT;
- return page;
- }
- }
-
- EXIT;
- return NULL;
-} /* obdfs_find_page_index */
-
-
-/* call and free pages from Linux page cache: called with io lock on inodes */
-int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io,
- obd_count num_obdos, struct obdo **obdos,
- obd_count *oa_bufs, struct page **pages, char **bufs,
- obd_size *counts, obd_off *offsets, obd_flag *flags)
-{
- int err;
-
- ENTRY;
- CDEBUG(D_INFO, "writing %d page(s), %d obdo(s) in vector\n",
- num_io, num_obdos);
- if (obd_debug_level & D_INFO) { /* DEBUGGING */
- int i;
- printk("OBDOS: ");
- for (i = 0; i < num_obdos; i++)
- printk("%ld:0x%p ", (long)obdos[i]->o_id, obdos[i]);
-
- printk("\nPAGES: ");
- for (i = 0; i < num_io; i++)
- printk("0x%p ", pages[i]);
- printk("\n");
- }
-
- err = obd_brw(OBD_BRW_WRITE, IID(inodes[0]), num_obdos, obdos,
- oa_bufs, pages, counts, offsets, flags);
-
- CDEBUG(D_INFO, "BRW done\n");
- /* release the pages from the page cache */
- while (num_io-- > 0) {
- CDEBUG(D_INFO, "calling put_page for %p, index %ld\n",
- pages[num_io], pages[num_io]->index);
- put_page(pages[num_io]);
- }
- CDEBUG(D_INFO, "put_page done\n");
-
- while (num_obdos-- > 0) {
- CDEBUG(D_INFO, "free obdo %ld\n",(long)obdos[num_obdos]->o_id);
- /* copy o_blocks to i_blocks */
- obdfs_set_size (inodes[num_obdos], obdos[num_obdos]->o_size);
- //obdfs_to_inode(inodes[num_obdos], obdos[num_obdos]);
- obdo_free(obdos[num_obdos]);
- }
- CDEBUG(D_INFO, "obdo_free done\n");
- EXIT;
- return err;
-}
-
-
-/*
- * Add a page to the write request cache list for later writing.
- * ASYNCHRONOUS write method.
- */
-static int obdfs_add_page_to_cache(struct inode *inode, struct page *page)
-{
- int err = 0;
- ENTRY;
-
- /* The PG_obdcache bit is cleared by obdfs_pgrq_del() BEFORE the page
- * is written, so at worst we will write the page out twice.
- *
- * If the page has the PG_obdcache bit set, then the inode MUST be
- * on the superblock dirty list so we don't need to check this.
- * Dirty inodes are removed from the superblock list ONLY when they
- * don't have any more cached pages. It is possible to have an inode
- * with no dirty pages on the superblock list, but not possible to
- * have an inode with dirty pages NOT on the superblock dirty list.
- */
- if (!OBDAddCachePage(page)) {
- struct obdfs_pgrq *pgrq;
- pgrq = kmem_cache_alloc(obdfs_pgrq_cachep, SLAB_KERNEL);
- if (!pgrq) {
- OBDClearCachePage(page);
- EXIT;
- return -ENOMEM;
- }
- /* not really necessary since we set all pgrq fields here
- memset(pgrq, 0, sizeof(*pgrq));
- */
-
- pgrq->rq_page = page;
- pgrq->rq_jiffies = jiffies;
- get_page(pgrq->rq_page);
-
- obd_down(&obdfs_i2sbi(inode)->osi_list_mutex);
- list_add(&pgrq->rq_plist, obdfs_iplist(inode));
- obdfs_cache_count++;
- //CERROR("-- count %d\n", obdfs_cache_count);
-
- /* If inode isn't already on superblock inodes list, add it.
- *
- * We increment the reference count on the inode to keep it
- * from being freed from memory. This _should_ be an iget()
- * with an iput() in both flush_reqs() and put_inode(), but
- * since put_inode() is called from iput() we can't call iput()
- * again there. Instead we just increment/decrement i_count,
- * which is mostly what iget/iput do for an inode in memory.
- */
- if ( list_empty(obdfs_islist(inode)) ) {
- atomic_inc(&inode->i_count);
- CDEBUG(D_INFO,
- "adding inode %ld to superblock list %p\n",
- inode->i_ino, obdfs_slist(inode));
- list_add(obdfs_islist(inode), obdfs_slist(inode));
- }
- obd_up(&obdfs_i2sbi(inode)->osi_list_mutex);
-
- }
-
- /* XXX For testing purposes, we can write out the page here.
- err = obdfs_flush_reqs(obdfs_slist(inode), ~0UL);
- */
-
- EXIT;
- return err;
-} /* obdfs_add_page_to_cache */
-
-void rebalance(void)
-{
- if (obdfs_cache_count > 60000) {
- CERROR("-- count %ld\n", obdfs_cache_count);
- //obdfs_flush_dirty_pages(~0UL);
- CERROR("-- count %ld\n", obdfs_cache_count);
- }
-}
-
-
-
-/* select between SYNC and ASYNC I/O methods */
-int obdfs_do_writepage(struct page *page, int sync)
-{
- struct inode *inode = page->mapping->host;
- int err;
-
- ENTRY;
- if ( sync )
- err = obdfs_brw(OBD_BRW_WRITE, inode, page, 1);
- else {
- err = obdfs_add_page_to_cache(inode, page);
- CDEBUG(D_INFO, "DO_WR ino: %ld, page %p, err %d, uptodate %d\n",
- inode->i_ino, page, err, Page_Uptodate(page));
- }
-
- if ( !err ) {
- SetPageUptodate(page);
- set_page_clean(page);
- }
- EXIT;
- return err;
-} /* obdfs_do_writepage */
-
-
-
-
-#endif
-
-int obdfs_commit_write(struct file *file, struct page *page, unsigned from, unsigned to)
-{
- struct inode *inode = page->mapping->host;
- int rc = 0;
- loff_t len = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
- ENTRY;
- CDEBUG(D_INODE, "commit write ino %ld (end at %Ld) from %d to %d ,ind %ld\n",
- inode->i_ino, len, from, to, page->index);
-
-
- if (cache_writes == 0) {
- rc = obdfs_commit_page(page, 1, from, to);
- }
-
- if (len > inode->i_size) {
- obdfs_set_size(inode, len);
- }
-
- kunmap(page);
- EXIT;
- return rc;
-}
-
-
-/*
- * This does the "real" work of the write. The generic routine has
- * allocated the page, locked it, done all the page alignment stuff
- * calculations etc. Now we should just copy the data from user
- * space and write it back to the real medium..
- *
- * If the writer ends up delaying the write, the writer needs to
- * increment the page use counts until he is done with the page.
- *
- * Return value is the number of bytes written.
- */
-int obdfs_write_one_page(struct file *file, struct page *page,
- unsigned long offset, unsigned long bytes,
- const char * buf)
-{
- struct inode *inode = file->f_dentry->d_inode;
- int err;
-
- ENTRY;
- /* We check for complete page writes here, as we then don't have to
- * get the page before writing over everything anyways.
- */
- if (!Page_Uptodate(page) && (offset != 0 || bytes != PAGE_SIZE)) {
- err = obdfs_brw(OBD_BRW_READ, inode, page, 0);
- if ( err )
- return err;
- SetPageUptodate(page);
- }
-
- if (copy_from_user((u8*)page_address(page) + offset, buf, bytes))
- return -EFAULT;
-
- lock_kernel();
- err = obdfs_writepage(page);
- unlock_kernel();
-
- return (err < 0 ? err : bytes);
-} /* obdfs_write_one_page */
-
-/*
- * return an up to date page:
- * - if locked is true then is returned locked
- * - if create is true the corresponding disk blocks are created
- * - page is held, i.e. caller must release the page
- *
- * modeled on NFS code.
- */
-struct page *obdfs_getpage(struct inode *inode, unsigned long offset,
- int create, int locked)
-{
- struct page * page;
- int index;
- int err;
-
- ENTRY;
-
- offset = offset & PAGE_CACHE_MASK;
- CDEBUG(D_INFO, "ino: %ld, offset %ld, create %d, locked %d\n",
- inode->i_ino, offset, create, locked);
- index = offset >> PAGE_CACHE_SHIFT;
-
- page = grab_cache_page(&inode->i_data, index);
-
- /* Yuck, no page */
- if (! page) {
- CERROR("grab_cache_page says no dice ...\n");
- EXIT;
- return NULL;
- }
-
- /* now check if the data in the page is up to date */
- if ( Page_Uptodate(page)) {
- if (!locked) {
- if (PageLocked(page))
- UnlockPage(page);
- } else {
- CERROR("expecting locked page\n");
- }
- EXIT;
- return page;
- }
-
- err = obdfs_brw(OBD_BRW_READ, inode, page, create);
-
- if ( err ) {
- SetPageError(page);
- UnlockPage(page);
- EXIT;
- return page;
- }
-
- if ( !locked )
- UnlockPage(page);
- SetPageUptodate(page);
- EXIT;
- return page;
-} /* obdfs_getpage */
-
-
-void obdfs_truncate(struct inode *inode)
-{
- struct obdo *oa;
- int err;
- ENTRY;
-
- //obdfs_dequeue_pages(inode);
- oa = obdo_alloc();
- if ( !oa ) {
- err = -ENOMEM;
- CERROR("obdo_alloc failed!\n");
- } else {
- oa->o_valid = (__u32)OBD_MD_FLNOTOBD;
- obdfs_from_inode(oa, inode);
-
- CDEBUG(D_INFO, "calling punch for %ld (%Lu bytes at 0)\n",
- (long)oa->o_id, (unsigned long long)oa->o_size);
- err = obd_punch(IID(inode), oa, oa->o_size, 0);
-
- obdo_free(oa);
- }
-
- if (err) {
- CERROR("obd_truncate fails (%d)\n", err);
- EXIT;
- return;
- }
- EXIT;
-} /* obdfs_truncate */
-
-struct address_space_operations obdfs_aops = {
- readpage: obdfs_readpage,
- writepage: obdfs_writepage,
- sync_page: block_sync_page,
- prepare_write: obdfs_prepare_write,
- commit_write: obdfs_commit_write,
- bmap: NULL
-};
+++ /dev/null
-
-/*
- * OBDFS Super operations
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Copryright (C) 1996 Peter J. Braam <braam@stelias.com>
- * Copryright (C) 1999 Stelias Computing Inc. <braam@stelias.com>
- * Copryright (C) 1999 Seagate Technology Inc.
- * Copryright (C) 2001 Mountain View Data, Inc.
- * Copryright (C) 2002 Cluster File Systems, Inc.
- *
- */
-
-#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>
-#include <linux/locks.h>
-#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/vmalloc.h>
-#include <asm/segment.h>
-
-#define DEBUG_SUBSYSTEM S_OBDFS
-
-#include <linux/obd_support.h>
-#include <linux/obd_class.h>
-#include <linux/obdfs.h>
-
-struct list_head obdfs_super_list;
-extern struct address_space_operations obdfs_aops;
-struct super_operations obdfs_super_operations;
-long obdfs_cache_count = 0;
-long obdfs_mutex_start = 0;
-
-static char *obdfs_read_opt(const char *opt, char *data)
-{
- char *value;
- char *retval;
-
- CDEBUG(D_INFO, "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 void obdfs_options(char *options, char **dev, char **vers)
-{
- char *this_char;
-
- if (!options)
- return;
-
- for (this_char = strtok (options, ",");
- this_char != NULL;
- this_char = strtok (NULL, ",")) {
- CDEBUG(D_INFO, "this_char %s\n", this_char);
- if ( (!*dev && (*dev = obdfs_read_opt("device", this_char)))||
- (!*vers && (*vers = obdfs_read_opt("version", this_char))) )
- continue;
-
- }
-}
-
-static struct super_block * obdfs_read_super(struct super_block *sb,
- void *data, int silent)
-{
- struct inode *root = 0;
- struct obdfs_sb_info *sbi = (struct obdfs_sb_info *)(&sb->u.generic_sbp);
- struct obd_device *obddev;
- char *device = NULL;
- char *version = NULL;
- int connected = 0;
- int devno;
- int err;
- unsigned long blocksize;
- unsigned long blocksize_bits;
- obd_id root_ino;
- int scratch;
- struct obdo *oa;
-
- ENTRY;
- MOD_INC_USE_COUNT;
-
- memset(sbi, 0, sizeof(*sbi));
-
- CDEBUG(D_INFO, "\n");
- obdfs_options(data, &device, &version);
- if (!device) {
- CERROR("no device\n");
- EXIT;
- goto ERR;
- }
-
- devno = simple_strtoul(device, NULL, 0);
- CDEBUG(D_INFO, "\n");
- if (devno >= MAX_OBD_DEVICES) {
- CERROR("device of %s too high (%d)\n", device, devno);
- EXIT;
- goto ERR;
- }
-
- CDEBUG(D_INFO, "\n");
-
- obddev = &obd_dev[devno];
- sbi->osi_obd = obddev;
-
- err = obd_connect(&sbi->osi_conn, obddev);
- if (err) {
- CERROR("OBDFS: cannot connect to %s\n", device);
- EXIT;
- goto ERR;
- }
-
- connected = 1;
- CDEBUG(D_INFO, "\n");
- /* list of dirty inodes, and a mutex to hold while modifying it */
- INIT_LIST_HEAD(&sbi->osi_inodes);
- init_MUTEX (&sbi->osi_list_mutex);
-
- CDEBUG(D_INFO, "\n");
- sbi->osi_super = sb;
-
- CDEBUG(D_INFO, "\n");
- err = obd_get_info(&sbi->osi_conn, strlen("blocksize"),
- "blocksize", &scratch,
- (void *)&blocksize);
- if (err) {
- CERROR("getinfo call to drive failed (blocksize)\n");
- EXIT;
- goto ERR;
- }
-
- CDEBUG(D_INFO, "\n");
- err = obd_get_info(&sbi->osi_conn, strlen("blocksize_bits"),
- "blocksize_bits", &scratch,
- (void *)&blocksize_bits);
- if (err) {
- CERROR("getinfo call to drive failed (blocksize_bits)\n");
- EXIT;
- goto ERR;
- }
-
- CDEBUG(D_INFO, "\n");
- err = obd_get_info(&sbi->osi_conn, strlen("root_ino"),
- "root_ino", &scratch, (void *)&root_ino);
- if (err) {
- CERROR("getinfo call to drive failed (root_ino)\n");
- EXIT;
- goto ERR;
- }
-
- CDEBUG(D_INFO, "\n");
- sb->s_maxbytes = 1LL << 36;
- CERROR("Max bytes: %Lx\n", sb->s_maxbytes);
- sb->s_blocksize = PAGE_SIZE;
- sb->s_blocksize_bits = (unsigned char)PAGE_SHIFT;
- sb->s_magic = OBDFS_SUPER_MAGIC;
- sb->s_op = &obdfs_super_operations;
-
- /* XXX how to get "sb->s_flags |= MS_RDONLY" here for snapshots? */
-
- /* make root inode */
- CDEBUG(D_INFO, "\n");
- oa = obdo_fromid(&sbi->osi_conn, root_ino, S_IFDIR,
- (__u32)(OBD_MD_FLNOTOBD | OBD_MD_FLBLOCKS));
- CDEBUG(D_INFO, "mode %o\n", oa->o_mode);
- if (IS_ERR(oa)) {
- CERROR("obdo_fromid failed\n");
- iput(root);
- EXIT;
- goto ERR;
- }
- CDEBUG(D_INFO, "\n");
- root = iget4(sb, (ino_t)root_ino, NULL, oa);
- obdo_free(oa);
- CDEBUG(D_INFO, "\n");
- if (!root) {
- CERROR("OBDFS: bad iget4 for root\n");
- sb->s_dev = 0;
- err = -ENOENT;
- EXIT;
- goto ERR;
- }
-
- CDEBUG(D_INFO, "sbdev %d, rootino: %Ld, dev %s, "
- "minor: %d, blocksize: %ld, blocksize bits %ld\n",
- sb->s_dev, (long long)root_ino, device, MINOR(devno),
- blocksize, blocksize_bits);
- sb->s_root = d_alloc_root(root);
- list_add(&sbi->osi_list, &obdfs_super_list);
- OBD_FREE(device, strlen(device) + 1);
- if (version)
- OBD_FREE(version, strlen(version) + 1);
- EXIT;
- return sb;
-
-ERR:
- MOD_DEC_USE_COUNT;
- if (device)
- OBD_FREE(device, strlen(device) + 1);
- if (version)
- OBD_FREE(version, strlen(version) + 1);
- if (connected)
- obd_disconnect(&sbi->osi_conn);
-
- if (sbi) {
- sbi->osi_super = NULL;
- }
- if (root) {
- iput(root);
- }
- sb->s_dev = 0;
- return NULL;
-} /* obdfs_read_super */
-
-
-static void obdfs_put_super(struct super_block *sb)
-{
- struct obdfs_sb_info *sbi;
-
- ENTRY;
- sb->s_dev = 0;
-
- sbi = (struct obdfs_sb_info *) &sb->u.generic_sbp;
- //obdfs_flush_reqs(&sbi->osi_inodes, ~0UL);
-
- obd_disconnect(ID(sb));
- list_del(&sbi->osi_list);
-
- CERROR("OBDFS: Bye bye.\n");
-
- MOD_DEC_USE_COUNT;
- EXIT;
-} /* obdfs_put_super */
-
-
-void obdfs_do_change_inode(struct inode *inode, int valid)
-{
- struct obdo *oa;
- int err;
-
- ENTRY;
- oa = obdo_alloc();
- if ( !oa ) {
- CERROR("obdo_alloc failed\n");
- EXIT;
- return;
- }
-
- oa->o_valid = OBD_MD_FLNOTOBD & (valid | OBD_MD_FLID);
- obdfs_from_inode(oa, inode);
- oa->o_mode = inode->i_mode;
- err = obd_setattr(IID(inode), oa);
-
- if ( err )
- CERROR("obd_setattr fails (%d)\n", err);
-
- EXIT;
- obdo_free(oa);
-} /* obdfs_write_inode */
-
-void obdfs_change_inode(struct inode *inode, int mask)
-{
- return obdfs_do_change_inode(inode, OBD_MD_FLNLINK);
-}
-
-
-extern void write_inode_pages(struct inode *);
-/* This routine is called from iput() (for each unlink on the inode).
- * We can't put this call into delete_inode() since that is called only
- * when i_count == 0, and we need to keep a reference on the inode while
- * it is in the page cache, which means i_count > 0. Catch 22.
- */
-static void obdfs_put_inode(struct inode *inode)
-{
- ENTRY;
- if (inode->i_nlink && (atomic_read(&inode->i_count) == 1)) {
- write_inode_pages(inode);
- EXIT;
- return;
- }
-
- //obdfs_dequeue_pages(inode);
- EXIT;
-} /* obdfs_put_inode */
-
-
-static void obdfs_delete_inode(struct inode *inode)
-{
- obdfs_do_change_inode(inode, ~0);
- clear_inode(inode);
-}
-#if 0
-{
- struct obdo *oa;
- int err;
-
- ENTRY;
- oa = obdo_alloc();
- if ( !oa ) {
- CERROR("obdo_alloc failed\n");
- EXIT;
- return;
- }
- oa->o_valid = OBD_MD_FLNOTOBD;
- obdfs_from_inode(oa, inode);
-
- /* XXX how do we know that this inode is now clean? */
- CERROR("delete_inode ------> link %d\n", inode->i_nlink);
- ODEBUG(oa);
- err = obd_destroy(IID(inode), oa);
- obdo_free(oa);
- clear_inode(inode);
- if (err) {
- CERROR("obd_destroy fails (%d)\n", err);
- EXIT;
- return;
- }
-
- EXIT;
-} /* obdfs_delete_inode */
-#endif
-
-
-static int obdfs_attr2inode(struct inode * inode, struct iattr * attr)
-{
- unsigned int ia_valid = attr->ia_valid;
- int error = 0;
-
- if (ia_valid & ATTR_SIZE) {
- error = vmtruncate(inode, attr->ia_size);
- if (error)
- goto out;
- }
-
- 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 obdfs_setattr(struct dentry *de, struct iattr *attr)
-{
- struct inode *inode = de->d_inode;
- struct obdo *oa;
- int err;
-
- ENTRY;
- oa = obdo_alloc();
- if ( !oa ) {
- CERROR("obdo_alloc failed\n");
- return -ENOMEM;
- }
-
- obdfs_attr2inode(inode, attr);
- oa->o_id = inode->i_ino;
- oa->o_mode = inode->i_mode;
- obdo_from_iattr(oa, attr);
- err = obd_setattr(IID(inode), oa);
-
- if ( err )
- CERROR("obd_setattr fails (%d)\n", err);
-
- EXIT;
- obdo_free(oa);
- return err;
-} /* obdfs_setattr */
-
-
-
-static int obdfs_statfs(struct super_block *sb, struct statfs *sfs)
-{
- int rc;
-
- ENTRY;
-
- rc = obd_statfs(ID(sb), sfs);
- if (rc)
- CERROR("obd_statfs fails: rc = %d\n", rc);
- else
- CDEBUG(D_SUPER, "statfs returns avail %ld\n", sfs->f_bavail);
-
- RETURN(rc);
-}
-
-static inline void obdfs_read_inode2(struct inode *inode, void *opaque)
-{
- struct obdo *oa = opaque;
-
- ENTRY;
- obdfs_to_inode(inode, oa);
-
- INIT_LIST_HEAD(obdfs_iplist(inode)); /* list of dirty pages on inode */
- INIT_LIST_HEAD(obdfs_islist(inode)); /* list of inodes in superblock */
-
- /* OIDEBUG(inode); */
-
- if (S_ISREG(inode->i_mode)) {
- inode->i_op = &obdfs_file_inode_operations;
- inode->i_fop = &obdfs_file_operations;
- inode->i_mapping->a_ops = &obdfs_aops;
- EXIT;
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &obdfs_dir_inode_operations;
- inode->i_fop = &obdfs_dir_operations;
- inode->i_mapping->a_ops = &obdfs_aops;
- EXIT;
- } else if (S_ISLNK(inode->i_mode)) {
- if (inode->i_blocks) {
- inode->i_op = &obdfs_symlink_inode_operations;
- inode->i_mapping->a_ops = &obdfs_aops;
- }else {
- inode->i_op = &obdfs_fast_symlink_inode_operations;
- }
- EXIT;
- } else {
- init_special_inode(inode, inode->i_mode,
- ((int *)obdfs_i2info(inode)->oi_inline)[0]);
- }
-
- EXIT;
- return;
-}
-
-/* exported operations */
-struct super_operations obdfs_super_operations =
-{
- read_inode2: obdfs_read_inode2,
- put_inode: obdfs_put_inode,
- delete_inode: obdfs_delete_inode,
- put_super: obdfs_put_super,
- statfs: obdfs_statfs
-};
-
-
-struct file_system_type obdfs_fs_type = {
- "obdfs", 0, obdfs_read_super, NULL
-};
-
-int init_obdfs(void)
-{
- //int err;
-
- printk(KERN_INFO "OBDFS v0.1, info@clusterfs.com\n");
-
- obdfs_sysctl_init();
-
- INIT_LIST_HEAD(&obdfs_super_list);
- //err = obdfs_init_pgrqcache();
- //if (err)
- //return err;
-
- //obdfs_flushd_init();
- return register_filesystem(&obdfs_fs_type);
-}
-
-
-
-
-#ifdef MODULE
-int init_module(void)
-{
- return init_obdfs();
-}
-
-void cleanup_module(void)
-{
- ENTRY;
-
- //obdfs_flushd_cleanup();
- obdfs_sysctl_clean();
- //obdfs_cleanup_pgrqcache();
- unregister_filesystem(&obdfs_fs_type);
- CDEBUG(D_MALLOC, "OBDFS mem used %ld\n", obd_memory);
- EXIT;
-}
-
-#endif
+++ /dev/null
-/*
- * linux/fs/ext2/symlink.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/symlink.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * ext2 symlink handling code
- *
- * Modified for OBDFS.
- * Re-written Oct 2001.
- *
- * Copyright (C) 2001 Cluster File Systems, Inc. (author: braam@clusterfs.com)
- */
-
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-
-#define DEBUG_SUBSYSTEM S_OBDFS
-
-#include <linux/obd_support.h> /* for ENTRY and EXIT only */
-#include <linux/obdfs.h>
-
-static int obdfs_fast_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
- char *s = obdfs_i2info(dentry->d_inode)->oi_inline;
- return vfs_readlink(dentry, buffer, buflen, s);
-}
-
-static int obdfs_fast_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
- char *s = obdfs_i2info(dentry->d_inode)->oi_inline;
- return vfs_follow_link(nd, s);
-}
-
-extern int obdfs_setattr(struct dentry *de, struct iattr *attr);
-struct inode_operations obdfs_fast_symlink_inode_operations = {
- readlink: obdfs_fast_readlink,
- follow_link: obdfs_fast_follow_link,
- setattr: obdfs_setattr
-};
-
-static int obdfs_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
- struct page *page = NULL;
- int res;
-
- ENTRY;
- page = obdfs_getpage(dentry->d_inode, 0, 0, 0);
- if (!page) {
- EXIT;
- return 0;
- }
- res = vfs_readlink(dentry, buffer, buflen, (char *)page_address(page));
- page_cache_release(page);
- EXIT;
- return res;
-} /* obdfs_readlink */
-
-static int obdfs_follow_link(struct dentry * dentry,
- struct nameidata *nd)
-{
- struct page *page = NULL;
- int res;
-
- ENTRY;
- page = obdfs_getpage(dentry->d_inode, 0, 0, 0);
- if (!page) {
- dput(nd->dentry);
- EXIT;
- return -EIO;
- }
- res = vfs_follow_link(nd, (char *)page_address(page));
- page_cache_release(page);
- EXIT;
- return res;
-}
-
-struct inode_operations obdfs_symlink_inode_operations = {
- readlink: obdfs_readlink,
- follow_link: obdfs_follow_link,
- setattr: obdfs_setattr
-};
+++ /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 <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 *obdfs_table_header = NULL;
-
-int obdfs_debug_level = 0;
-int obdfs_print_entry = 1;
-
-
-#define OBDFS_SYSCTL 1
-
-#define OBDFS_DEBUG 1 /* control debugging */
-#define OBDFS_ENTRY 2 /* control enter/leave pattern */
-#define OBDFS_TIMEOUT 3 /* timeout on upcalls to become intrble */
-#define OBDFS_HARD 4 /* mount type "hard" or "soft" */
-#define OBDFS_VARS 5
-#define OBDFS_INDEX 6
-#define OBDFS_RESET 7
-
-#define OBDFS_VARS_SLOT 2
-
-static ctl_table obdfs_table[] = {
- {OBDFS_DEBUG, "debug", &obdfs_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
- {OBDFS_ENTRY, "trace", &obdfs_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
- { 0 }
-};
-
-static ctl_table top_table[] = {
- {OBDFS_SYSCTL, "obdfs", NULL, 0, 0555, obdfs_table},
- {0}
-};
-
-void obdfs_sysctl_init (void)
-{
-
-#ifdef CONFIG_SYSCTL
- if ( !obdfs_table_header )
- obdfs_table_header = register_sysctl_table(top_table, 0);
-#endif
-}
-
-void obdfs_sysctl_clean (void)
-{
-#ifdef CONFIG_SYSCTL
- if ( obdfs_table_header )
- unregister_sysctl_table(obdfs_table_header);
- obdfs_table_header = NULL;
-#endif
-}
+++ /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 l_net.c
-osc_SOURCES = osc_request.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
-
-l_net.c:
- test -e l_net.c || ln -sf $(top_srcdir)/lib/l_net.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) 2001, 2002 Cluster File Systems, Inc.
- *
- * This code is issued under the GNU General Public License.
- * See the file COPYING in this distribution
- *
- * Author Peter Braam <braam@clusterfs.com>
- *
- * 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_OSC
-
-#include <linux/module.h>
-#include <linux/lustre_dlm.h>
-#include <linux/lustre_mds.h> /* for mds_objid */
-#include <linux/obd_ost.h>
-#include <linux/obd_lov.h>
-#include <linux/init.h>
-#include <linux/lustre_ha.h>
-
-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_req2(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);
- rc = ptlrpc_check_status(request, rc);
- 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_free_req(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_req2(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);
- rc = ptlrpc_check_status(request, rc);
- 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_free_req(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_req2(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);
- rc = ptlrpc_check_status(request, rc);
- 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_free_req(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_req2(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);
- rc = ptlrpc_check_status(request, rc);
- GOTO(out, rc);
-
- out:
- ptlrpc_free_req(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;
- int rc, size = sizeof(*body);
- ENTRY;
-
- if (!oa) {
- CERROR("oa NULL\n");
- RETURN(-EINVAL);
- }
-
- if (!ea) {
- LBUG();
- }
-
- if (!*ea) {
- OBD_ALLOC(*ea, oa->o_easize);
- if (!*ea)
- RETURN(-ENOMEM);
- (*ea)->lmd_easize = oa->o_easize;
- }
-
- request = ptlrpc_prep_req2(conn, OST_CREATE, 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);
- rc = ptlrpc_check_status(request, rc);
- if (rc)
- GOTO(out, rc);
-
- body = lustre_msg_buf(request->rq_repmsg, 0);
- memcpy(oa, &body->oa, sizeof(*oa));
-
- (*ea)->lmd_object_id = oa->o_id;
- (*ea)->lmd_stripe_count = 1;
- EXIT;
- out:
- ptlrpc_free_req(request);
- 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_req2(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 blocks and size fields in the oa with start/end */
-#warning FIXME: endianness, size=start, blocks=end?
- body->oa.o_blocks = start;
- body->oa.o_size = end;
- body->oa.o_valid |= OBD_MD_FLBLOCKS | OBD_MD_FLSIZE;
-
- request->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(request);
- rc = ptlrpc_check_status(request, rc);
- if (rc)
- GOTO(out, rc);
-
- body = lustre_msg_buf(request->rq_repmsg, 0);
- memcpy(oa, &body->oa, sizeof(*oa));
-
- EXIT;
- out:
- ptlrpc_free_req(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_req2(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);
- rc = ptlrpc_check_status(request, rc);
- if (rc)
- GOTO(out, rc);
-
- body = lustre_msg_buf(request->rq_repmsg, 0);
- memcpy(oa, &body->oa, sizeof(*oa));
-
- EXIT;
- out:
- ptlrpc_free_req(request);
- return rc;
-}
-
-struct osc_brw_cb_data {
- brw_callback_t callback;
- void *cb_data;
- void *obd_data;
- size_t obd_size;
-};
-
-/* 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->b_page_list) {
- struct ptlrpc_bulk_page *bulk;
- bulk = list_entry(tmp, struct ptlrpc_bulk_page, b_link);
-
- kunmap(bulk->b_page);
- }
-
- ptlrpc_bulk_decref(desc);
- EXIT;
-}
-
-static void brw_finish(struct ptlrpc_bulk_desc *desc, void *data)
-{
- struct osc_brw_cb_data *cb_data = data;
- int err = 0;
- ENTRY;
-
- if (desc->b_flags & PTL_RPC_FL_TIMEOUT) {
- err = (desc->b_flags & PTL_RPC_FL_INTR ? -ERESTARTSYS :
- -ETIMEDOUT);
- }
-
- if (cb_data->callback)
- cb_data->callback(cb_data->cb_data, err, CB_PHASE_FINISH);
-
- OBD_FREE(cb_data->obd_data, cb_data->obd_size);
- OBD_FREE(cb_data, sizeof(*cb_data));
-
- /* We can't kunmap the desc from interrupt context, so we do it from
- * the bottom half above. */
- INIT_TQUEUE(&desc->b_queue, 0, 0);
- PREPARE_TQUEUE(&desc->b_queue, unmap_and_decref_bulk_desc, desc);
- schedule_task(&desc->b_queue);
-
- EXIT;
-}
-
-static int osc_brw_read(struct lustre_handle *conn, struct lov_stripe_md *md,
- obd_count page_count, struct brw_page *pga,
- brw_callback_t callback, struct io_cb_data *data)
-{
- struct ptlrpc_connection *connection = client_conn2cli(conn)->cl_conn;
- struct ptlrpc_request *request = NULL;
- struct ptlrpc_bulk_desc *desc = NULL;
- struct ost_body *body;
- struct osc_brw_cb_data *cb_data = NULL;
- int rc, size[3] = {sizeof(*body)};
- void *iooptr, *nioptr;
- int mapped = 0;
- __u32 xid;
- ENTRY;
-
- size[1] = sizeof(struct obd_ioobj);
- size[2] = page_count * sizeof(struct niobuf_remote);
-
- request = ptlrpc_prep_req2(conn, 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->b_portal = OST_BULK_PORTAL;
- desc->b_cb = brw_finish;
- OBD_ALLOC(cb_data, sizeof(*cb_data));
- if (!cb_data)
- GOTO(out_desc, rc = -ENOMEM);
-
- cb_data->callback = callback;
- cb_data->cb_data = data;
- data->desc = desc;
- desc->b_cb_data = cb_data;
-
- 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_write case */
-
- spin_lock(&connection->c_lock);
- xid = ++connection->c_xid_out; /* single xid for all pages */
- spin_unlock(&connection->c_lock);
-
- 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->b_xid = xid; /* single xid for all pages */
-
- bulk->b_buf = kmap(pga[mapped].pg);
- bulk->b_page = pga[mapped].pg;
- bulk->b_buflen = PAGE_SIZE;
- ost_pack_niobuf(&nioptr, pga[mapped].off, pga[mapped].count,
- pga[mapped].flag, bulk->b_xid);
- }
-
- /*
- * Register the bulk first, because the reply could arrive out of order,
- * and we want to be ready for the bulk data.
- *
- * The reference is released when brw_finish is complete.
- *
- * On error, we never do the brw_finish, so we handle all decrefs.
- */
- rc = ptlrpc_register_bulk(desc);
- if (rc)
- GOTO(out_unmap, rc);
-
- request->rq_replen = lustre_msg_size(1, size);
- rc = ptlrpc_queue_wait(request);
- rc = ptlrpc_check_status(request, rc);
-
- /* XXX: Mike, this is the only place I'm not sure of. If we have
- * an error here, will we have always called brw_finish? If no,
- * then out_req will not clean up and we should go to out_desc.
- * If maybe, then we are screwed, and we need to set things up
- * so that bulk_sink_callback is called for each bulk page,
- * even on error so brw_finish is always called. It would need
- * to be passed an error code as a parameter to know what to do.
- *
- * That would also help with the partial completion case, so
- * we could say in brw_finish "these pages are done, don't
- * restart them" and osc_brw callers can know this.
- */
- if (rc)
- GOTO(out_req, rc);
-
- /* Callbacks cause asynchronous handling. */
- rc = callback(data, 0, CB_PHASE_START);
-
- EXIT;
-out_req:
- ptlrpc_req_finished(request);
- RETURN(rc);
-
- /* Clean up on error. */
-out_unmap:
- while (mapped-- > 0)
- kunmap(page_array[mapped]);
- OBD_FREE(cb_data, sizeof(*cb_data));
-out_desc:
- 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,
- brw_callback_t callback, struct io_cb_data *data)
-{
- struct ptlrpc_connection *connection = client_conn2cli(conn)->cl_conn;
- struct ptlrpc_request *request = NULL;
- struct ptlrpc_bulk_desc *desc = NULL;
- struct ost_body *body;
- struct niobuf_local *local = NULL;
- struct niobuf_remote *remote;
- struct osc_brw_cb_data *cb_data = NULL;
- int rc, j, size[3] = {sizeof(*body)};
- void *iooptr, *nioptr;
- int mapped = 0;
- ENTRY;
-
- size[1] = sizeof(struct obd_ioobj);
- size[2] = page_count * sizeof(*remote);
-
- request = ptlrpc_prep_req2(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->b_portal = OSC_BULK_PORTAL;
- desc->b_cb = brw_finish;
- OBD_ALLOC(cb_data, sizeof(*cb_data));
- if (!cb_data)
- GOTO(out_desc, rc = -ENOMEM);
-
- cb_data->callback = callback;
- cb_data->cb_data = data;
- data->desc = desc;
- desc->b_cb_data = cb_data;
-
- 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_cb, rc = -ENOMEM);
-
- cb_data->obd_data = local;
- cb_data->obd_size = page_count * sizeof(*local);
-
- for (mapped = 0; mapped < page_count; mapped++) {
- local[mapped].addr = kmap(pga[mapped].pg);
- 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);
- rc = ptlrpc_check_status(request, rc);
- 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->b_buf = (void *)(unsigned long)local[j].addr;
- bulk->b_buflen = local[j].len;
- bulk->b_xid = remote->xid;
- bulk->b_page = pga[j].pg;
- }
-
- if (desc->b_page_count != page_count)
- LBUG();
-
- /* Our reference is released when brw_finish is complete. */
- rc = ptlrpc_send_bulk(desc);
-
- /* XXX: Mike, same question as in osc_brw_read. */
- if (rc)
- GOTO(out_req, rc);
-
- /* Callbacks cause asynchronous handling. */
- rc = callback(data, 0, CB_PHASE_START);
-
- EXIT;
-out_req:
- ptlrpc_req_finished(request);
- return rc;
-
- /* Clean up on error. */
-out_unmap:
- while (mapped-- > 0)
- kunmap(pagearray[mapped]);
-
- OBD_FREE(local, page_count * sizeof(*local));
-out_cb:
- OBD_FREE(cb_data, sizeof(*cb_data));
-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, brw_callback_t callback,
- struct io_cb_data *data)
-{
- if (cmd & OBD_BRW_WRITE)
- return osc_brw_write(conn, md, page_count, pga, callback, data);
- else
- return osc_brw_read(conn, md, page_count, pga, callback, data);
-}
-
-static int osc_enqueue(struct lustre_handle *connh, struct lov_stripe_md *md,
- 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 = { md->lmd_object_id };
- struct obd_device *obddev = class_conn2obd(connh);
- struct ldlm_extent *extent = extentp;
- int rc;
- __u32 mode2;
-
- /* Filesystem locks are given a bit of special treatment: first we
- * fixup the lock to start and end on page boundaries. */
- extent->start &= PAGE_MASK;
- extent->end = (extent->end + PAGE_SIZE - 1) & PAGE_MASK;
-
- /* Next, search for already existing extent locks that will cover us */
- //osc_con2dlmcl(conn, &cl, &connection, &rconn);
- 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 0;
- }
-
- /* Next, search for locks that we can upgrade (if we're trying to write)
- * or are more than we need (if we're trying to read). Because the VFS
- * and page cache already protect us locally, lots of readers/writers
- * can share a single PW lock. */
- if (mode == LCK_PW)
- mode2 = LCK_PR;
- else
- mode2 = LCK_PW;
-
- rc = ldlm_lock_match(obddev->obd_namespace, &res_id, type, extent,
- sizeof(extent), mode2, lockh);
- if (rc == 1) {
- int flags;
- /* 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, mode);
- ldlm_lock_decref(lockh, mode2);
-
- if (mode == LCK_PR)
- return 0;
-
- rc = ldlm_cli_convert(lockh, mode, &flags);
- if (rc)
- LBUG();
-
- return rc;
- }
-
- 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_statfs(struct lustre_handle *conn, struct statfs *sfs)
-{
- struct ptlrpc_request *request;
- struct obd_statfs *osfs;
- int rc, size = sizeof(*osfs);
- ENTRY;
-
- request = ptlrpc_prep_req2(conn, OST_STATFS, 0, NULL, NULL);
- if (!request)
- RETURN(-ENOMEM);
-
- request->rq_replen = lustre_msg_size(1, &size);
-
- rc = ptlrpc_queue_wait(request);
- rc = ptlrpc_check_status(request, rc);
- if (rc) {
- CERROR("%s failed: rc = %d\n", __FUNCTION__, rc);
- GOTO(out, rc);
- }
-
- osfs = lustre_msg_buf(request->rq_repmsg, 0);
- obd_statfs_unpack(osfs, sfs);
-
- EXIT;
- out:
- ptlrpc_free_req(request);
- return rc;
-}
-
-static int osc_iocontrol(long 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;
-
- 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);
- }
-
- 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;
-
- if (data->ioc_inllen1)
- numthreads = simple_strtoul(data->ioc_inlbuf1, NULL, 0);
- else
- numthreads = 1;
-
- err = ldlm_regression_start(obddev, conn, numthreads);
- 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);
- }
- default:
- GOTO(out, err = -EINVAL);
- }
-out:
- return err;
-}
-
-struct obd_ops osc_obd_ops = {
- o_setup: client_obd_setup,
- o_cleanup: client_obd_cleanup,
- o_statfs: osc_statfs,
- 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_connect: client_obd_connect,
- o_disconnect: client_obd_disconnect,
- o_brw: osc_brw,
- o_punch: osc_punch,
- o_enqueue: osc_enqueue,
- o_cancel: osc_cancel,
- o_iocontrol: osc_iocontrol
-};
-
-static int __init osc_init(void)
-{
- return class_register_type(&osc_obd_ops, 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=page.c obd_pack.c l_net.c ll_pack.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
-
-page.c:
- test -e page.c || ln -sf $(top_srcdir)/lib/page.c
-
-l_net.c:
- test -e l_net.c || ln -sf $(top_srcdir)/lib/l_net.c
-
-ost_SOURCES = $(LINX) ost_handler.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) 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>
-
-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);
- 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;
- struct statfs sfs;
- int rc, size = sizeof(*osfs);
- ENTRY;
-
- rc = obd_statfs(conn, &sfs);
- if (rc) {
- CERROR("ost: statfs failed: rc %d\n", rc);
- req->rq_status = rc;
- RETURN(rc);
- }
-
- 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);
- obd_statfs_pack(osfs, &sfs);
- 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);
- 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);
- 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);
- 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);
-
- 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);
- memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
- req->rq_status = obd_punch(conn, &repbody->oa, NULL,
- repbody->oa.o_blocks, repbody->oa.o_size);
- 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);
- memcpy(&repbody->oa, &body->oa, sizeof(body->oa));
- req->rq_status = obd_setattr(conn, &repbody->oa, NULL);
- RETURN(0);
-}
-
-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;
- 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;
-
- 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);
- }
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc)
- RETURN(rc);
- OBD_ALLOC(local_nb, sizeof(*local_nb) * niocount);
- if (local_nb == NULL)
- RETURN(-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, NULL);
-
- if (req->rq_status)
- GOTO(out_local, 0);
-
- desc = ptlrpc_prep_bulk(req->rq_connection);
- if (desc == NULL)
- GOTO(out_local, rc = -ENOMEM);
- desc->b_portal = OST_BULK_PORTAL;
-
- for (i = 0; i < niocount; i++) {
- struct ptlrpc_bulk_page *bulk;
- bulk = ptlrpc_prep_bulk_page(desc);
- if (bulk == NULL)
- GOTO(out_bulk, rc = -ENOMEM);
- remote_nb = &(((struct niobuf_remote *)tmp2)[i]);
- bulk->b_xid = remote_nb->xid;
- bulk->b_buf = (void *)(unsigned long)local_nb[i].addr;
- bulk->b_buflen = PAGE_SIZE;
- }
-
- rc = ptlrpc_send_bulk(desc);
- if (rc)
- GOTO(out_bulk, rc);
-
-#warning OST must time out here.
- wait_event(desc->b_waitq, ptlrpc_check_bulk_sent(desc));
- if (desc->b_flags & PTL_RPC_FL_INTR)
- rc = -EINTR;
-
- /* 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_commitrw(cmd, conn, objcount,
- tmp1, niocount, local_nb, NULL);
-
-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;
- __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? */
-
- desc = ptlrpc_prep_bulk(req->rq_connection);
- if (desc == NULL)
- GOTO(fail_preprw, rc = -ENOMEM);
- desc->b_cb = NULL;
- desc->b_portal = OSC_BULK_PORTAL;
- desc->b_desc_private = desc_priv;
- memcpy(&(desc->b_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->b_xid = xid; /* single xid for all pages */
-
- bulk->b_buf = lnb->addr;
- bulk->b_page = lnb->page;
- bulk->b_flags = lnb->flags;
- bulk->b_dentry = lnb->dentry;
- bulk->b_buflen = PAGE_SIZE;
- bulk->b_cb = NULL;
-
- /* this advances remote_nb */
- ost_pack_niobuf((void **)&remote_nb, lnb->offset, lnb->len, 0,
- bulk->b_xid);
- }
-
- rc = ptlrpc_register_bulk(desc);
- if (rc)
- GOTO(fail_bulk, rc);
-
- reply_sent = 1;
- ptlrpc_reply(req->rq_svc, req);
-
-#warning OST must time out here.
- wait_event(desc->b_waitq, desc->b_flags & PTL_BULK_FL_RCVD);
-
- rc = obd_commitrw(cmd, conn, objcount, tmp1, niocount, local_nb,
- desc->b_desc_private);
- ptlrpc_free_bulk(desc);
- EXIT;
-out_free:
- OBD_FREE(local_nb, niocount * sizeof(*local_nb));
-out:
- if (!reply_sent) {
- if (rc)
- 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->type != PTL_RPC_MSG_REQUEST) {
- CERROR("lustre_ost: wrong packet type sent %d\n",
- req->rq_reqmsg->type);
- GOTO(out, rc = -EINVAL);
- }
-
- 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, "setattr\n");
- OBD_FAIL_RETURN(OBD_FAIL_OST_OPEN_NET, 0);
- rc = ost_open(req);
- break;
- case OST_CLOSE:
- CDEBUG(D_INODE, "setattr\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);
- if (rc)
- break;
- RETURN(0);
- case LDLM_CONVERT:
- CDEBUG(D_INODE, "convert\n");
- OBD_FAIL_RETURN(OBD_FAIL_LDLM_CONVERT, 0);
- rc = ldlm_handle_convert(req);
- if (rc)
- break;
- RETURN(0);
- 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);
- 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;
-}
-
-#define OST_NUM_THREADS 6
-
-/* 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);
- if (err) {
- CERROR("fail to connect to device %d\n", data->ioc_dev);
- GOTO(error_dec, err = -EINVAL);
- }
-
- ost->ost_service = ptlrpc_init_svc(64 * 1024, OST_REQUEST_PORTAL,
- OSC_REPLY_PORTAL, "self",ost_handle);
- 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, "lustre_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);
-}
-
-/* use obd ops to offer management infrastructure */
-static struct obd_ops ost_obd_ops = {
- o_setup: ost_setup,
- o_cleanup: ost_cleanup,
-};
-
-static int __init ost_init(void)
-{
- class_register_type(&ost_obd_ops, LUSTRE_OST_NAME);
- return 0;
-}
-
-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/mm/slab.c Fri Dec 21 12:42:05 2001
-+++ lum/mm/slab.c Thu Aug 1 18:07:35 2002
-@@ -1187,6 +1187,57 @@
- * 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 (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;
-+ }
-+
-+ 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)
---- 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 *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.
- *
-@@ -228,13 +243,10 @@
- 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);
-@@ -334,13 +346,10 @@
- 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);
-@@ -1328,6 +1337,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
-@@ -1393,6 +1425,9 @@
- 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
---- 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)(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
-@@ -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,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 *);
---- 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_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)
-+
-+/* it_op MUST be first, or all of the initializing code will break */
-+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,17 +107,20 @@
- struct dentry_operations *d_op;
- struct super_block * d_sb; /* The root of the dentry tree */
- unsigned long d_vfs_flags;
-+ struct lookup_intent *d_it;
- void * d_fsdata; /* fs-specific data */
- unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
- };
-
- struct dentry_operations {
- int (*d_revalidate)(struct dentry *, int);
-+ int (*d_revalidate2)(struct dentry *, int, struct lookup_intent *);
- int (*d_hash) (struct dentry *, struct qstr *);
- int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
- int (*d_delete)(struct dentry *);
- void (*d_release)(struct dentry *);
- void (*d_iput)(struct dentry *, struct inode *);
-+ void (*d_intent_release)(struct dentry *);
- };
-
- /* 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)
-+{
-+ 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;
- }
-@@ -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;
-@@ -626,6 +655,7 @@
- else if (this.len == 2 && this.name[1] == '.')
- nd->last_type = LAST_DOTDOT;
- return_base:
-+ nd->dentry->d_it = it;
- return 0;
- out_dput:
- dput(dentry);
-@@ -633,15 +663,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)
-@@ -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;
-@@ -984,17 +1056,23 @@
- * The simplest case - just a plain lookup.
- */
- 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;
-+ dentry->d_it = it;
- goto ok;
- }
-
- /*
- * 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,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,
-@@ -1139,8 +1219,10 @@
- return 0;
-
- exit_dput:
-+ intent_release(dentry);
- dput(dentry);
- exit:
-+ intent_release(nd->dentry);
- 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);
- 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_MKNOD, mode };
-
- if (S_ISDIR(mode))
- return -EPERM;
-@@ -1252,11 +1344,12 @@
- 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;
- 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);
-@@ -1270,6 +1363,7 @@
- default:
- error = -EINVAL;
- }
-+ intent_release(dentry);
- dput(dentry);
- }
- up(&nd.dentry->d_inode->i_sem);
-@@ -1310,6 +1404,7 @@
- {
- int error = 0;
- char * tmp;
-+ struct lookup_intent it = { IT_MKDIR, mode };
-
- tmp = getname(pathname);
- error = PTR_ERR(tmp);
-@@ -1321,11 +1416,13 @@
- 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)) {
-+ 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);
-@@ -1407,6 +1504,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { IT_RMDIR, 0 };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1429,10 +1527,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);
-@@ -1476,6 +1576,7 @@
- char * name;
- struct dentry *dentry;
- struct nameidata nd;
-+ struct lookup_intent it = { IT_UNLINK, 0 };
-
- name = getname(pathname);
- if(IS_ERR(name))
-@@ -1489,14 +1590,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);
-@@ -1543,6 +1646,7 @@
- int error = 0;
- char * from;
- char * to;
-+ struct lookup_intent it = { IT_SYMLINK, 0 };
-
- 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);
-+ 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);
-@@ -1626,6 +1732,7 @@
- int error;
- char * from;
- char * to;
-+ struct lookup_intent it = { IT_LINK, 0 };
-
- from = getname(oldname);
- if(IS_ERR(from))
-@@ -1648,10 +1755,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);
-@@ -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;
-@@ -1748,12 +1858,14 @@
- } else
- double_down(&old_dir->i_zombie,
- &new_dir->i_zombie);
-+ new_dentry->d_it = it;
- if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir))
- error = -ENOENT;
- else 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;
-@@ -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;
-
-@@ -1802,10 +1915,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;
-@@ -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);
-@@ -1841,6 +1957,7 @@
- struct dentry * old_dir, * new_dir;
- struct dentry * old_dentry, *new_dentry;
- struct nameidata oldnd, newnd;
-+ struct lookup_intent it = {IT_RENAME, 0};
-
- if (path_init(oldname, LOOKUP_PARENT, &oldnd))
- error = path_walk(oldname, &oldnd);
-@@ -1868,7 +1985,9 @@
-
- double_lock(new_dir, old_dir);
-
-- old_dentry = lookup_hash(&oldnd.last, old_dir);
-+ it.it_op = IT_RENAME;
-+ it.it_mode = 0;
-+ 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);
- 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);
---- 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);
-
- int vfs_statfs(struct super_block *sb, struct statfs *buf)
- {
-@@ -94,14 +97,16 @@
- struct nameidata nd;
- struct inode * inode;
- int error;
-+ struct lookup_intent it = { 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 */
-@@ -144,6 +149,7 @@
- put_write_access(inode);
-
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -235,10 +241,12 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { 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;
-@@ -262,6 +270,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -279,11 +288,13 @@
- struct nameidata nd;
- struct inode * inode;
- struct iattr newattrs;
-+ struct lookup_intent it = { 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;
-@@ -306,6 +317,7 @@
- }
- error = notify_change(nd.dentry, &newattrs);
- dput_and_out:
-+ intent_release(nd.dentry);
- 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_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);
- path_release(&nd);
- }
-
-@@ -361,6 +375,7 @@
- int error;
- struct nameidata nd;
- char *name;
-+ struct lookup_intent it = { IT_GETATTR };
-
- name = getname(filename);
- error = PTR_ERR(name);
-@@ -369,11 +384,12 @@
-
- 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;
-
-+ nd.dentry->d_it = ⁢
- error = permission(nd.dentry->d_inode,MAY_EXEC);
- if (error)
- goto dput_and_out;
-@@ -381,6 +397,7 @@
- set_fs_pwd(current->fs, nd.mnt, nd.dentry);
-
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -421,6 +438,7 @@
- int error;
- struct nameidata nd;
- char *name;
-+ struct lookup_intent it = { IT_GETATTR };
-
- name = getname(filename);
- error = PTR_ERR(name);
-@@ -429,11 +447,12 @@
-
- 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;
-
-+ nd.dentry->d_it = ⁢
- error = permission(nd.dentry->d_inode,MAY_EXEC);
- if (error)
- goto dput_and_out;
-@@ -446,6 +465,7 @@
- set_fs_altroot();
- error = 0;
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -490,12 +510,13 @@
- struct inode * inode;
- int error;
- struct iattr newattrs;
--
-- error = user_path_walk(filename, &nd);
-+ struct lookup_intent it = { IT_SETATTR };
-+ 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;
-@@ -511,6 +532,7 @@
- error = notify_change(nd.dentry, &newattrs);
-
- dput_and_out:
-+ intent_release(nd.dentry);
- path_release(&nd);
- out:
- return error;
-@@ -580,10 +602,13 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { 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;
-@@ -593,10 +618,13 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { 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;
-@@ -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_OPEN, 0};
-
- 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);
- return f;
-
- cleanup_all:
-@@ -705,11 +741,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.
- */
---- lum-pristine/fs/stat.c Thu Sep 13 19:04:43 2001
-+++ lum/fs/stat.c Mon Aug 12 00:04:39 2002
-@@ -135,13 +135,15 @@
- asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
- {
- struct nameidata nd;
-+ struct lookup_intent it = {IT_GETATTR, 0};
- 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);
- 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_GETATTR, 0};
- 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);
- 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_GETATTR, 0};
- 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);
- 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_GETATTR, 0};
- 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);
- path_release(&nd);
- }
- return error;
-@@ -247,20 +255,21 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { 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);
- path_release(&nd);
- }
- return error;
-@@ -333,12 +342,14 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = {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);
- path_release(&nd);
- }
- return error;
-@@ -348,12 +359,14 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { 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);
- path_release(&nd);
- }
- return error;
-@@ -363,6 +376,7 @@
- {
- struct file * f;
- int err = -EBADF;
-+ struct lookup_intent it = { IT_GETATTR };
-
- f = fget(fd);
- if (f) {
+++ /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/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
-@@ -276,4 +276,9 @@
- }
- 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/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,13 @@
- EXPORT_SYMBOL(lock_may_write);
- EXPORT_SYMBOL(dcache_readdir);
-
-+/* lustre */
-+EXPORT_SYMBOL(panic_notifier_list);
-+EXPORT_SYMBOL(pagecache_lock_cacheline);
-+EXPORT_SYMBOL(kmem_cache_validate);
-+EXPORT_SYMBOL(do_kern_mount);
-+
-+
- /* 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)
-@@ -322,6 +343,13 @@
- 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, it);
- if (!dentry) {
- err = -EWOULDBLOCKIO;
- if (atomic)
- break;
-- dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);
-+ dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE, it);
- 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,12 @@
- error = path_lookup(to, LOOKUP_PARENT, &nd);
- if (error)
- goto out;
-- dentry = lookup_create(&nd, 0);
-+ 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,14 +2027,15 @@
- 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();
-
- dput(new_dentry);
---- 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,8 @@
- #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,13 @@
- {
- int error;
- struct nameidata nd;
--
-- error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
-+ struct lookup_intent it = { .it_op = IT_GETATTR };
-+
-+ 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,15 @@
- * 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,14 @@
- 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,19 @@
- 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,8 @@
-
- #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_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,13 @@
- {
- struct nameidata nd;
- int error;
-+ struct lookup_intent it = { 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,58 @@
- * 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/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,14 @@
- 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 enough?
-+ return virt_to_page(kaddr);
-+}
-+
-+
- int do_check_pgt_cache(int low, int high)
- {
- int freed = 0;
---- 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/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
---- 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,22 @@
- 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 = connmgr.c recovd.c connection.c rpc.c events.c service.c client.c niobuf.c pack_generic.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>
-
-void ptlrpc_init_client(struct recovd_obd *recovd,
- int (*recover)(struct ptlrpc_client *recover),
- int req_portal,
- int rep_portal, struct ptlrpc_client *cl)
-{
- memset(cl, 0, sizeof(*cl));
- cl->cli_recovd = recovd;
- cl->cli_recover = recover;
- if (recovd)
- recovd_cli_manage(recovd, cl);
- cl->cli_obd = NULL;
- cl->cli_request_portal = req_portal;
- cl->cli_reply_portal = rep_portal;
- INIT_LIST_HEAD(&cl->cli_delayed_head);
- INIT_LIST_HEAD(&cl->cli_sending_head);
- INIT_LIST_HEAD(&cl->cli_dying_head);
- spin_lock_init(&cl->cli_lock);
- sema_init(&cl->cli_rpc_sem, 32);
-}
-
-__u8 *ptlrpc_req_to_uuid(struct ptlrpc_request *req)
-{
- return req->rq_connection->c_remote_uuid;
-}
-
-struct ptlrpc_connection *ptlrpc_uuid_to_connection(char *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);
- if (c) {
- memcpy(c->c_remote_uuid, uuid, sizeof(c->c_remote_uuid));
- c->c_epoch++;
- }
-
- return c;
-}
-
-void ptlrpc_readdress_connection(struct ptlrpc_connection *conn, char *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->b_connection = ptlrpc_connection_addref(conn);
- atomic_set(&desc->b_refcount, 1);
- init_waitqueue_head(&desc->b_waitq);
- INIT_LIST_HEAD(&desc->b_page_list);
- ptl_set_inv_handle(&desc->b_md_h);
- ptl_set_inv_handle(&desc->b_me_h);
- }
-
- return desc;
-}
-
-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->b_desc = desc;
- list_add_tail(&bulk->b_link, &desc->b_page_list);
- desc->b_page_count++;
- }
- return bulk;
-}
-
-void ptlrpc_free_bulk(struct ptlrpc_bulk_desc *desc)
-{
- struct list_head *tmp, *next;
- ENTRY;
- if (desc == NULL) {
- EXIT;
- return;
- }
-
- list_for_each_safe(tmp, next, &desc->b_page_list) {
- struct ptlrpc_bulk_page *bulk;
- bulk = list_entry(tmp, struct ptlrpc_bulk_page, b_link);
- ptlrpc_free_bulk_page(bulk);
- }
-
- ptlrpc_put_connection(desc->b_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->b_link);
- bulk->b_desc->b_page_count--;
- OBD_FREE(bulk, sizeof(*bulk));
- EXIT;
-}
-
-struct ptlrpc_request *ptlrpc_prep_req(struct ptlrpc_client *cl,
- struct ptlrpc_connection *conn,
- int opcode, int count, int *lengths,
- char **bufs)
-{
- 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_TYPE_REQUEST;
- request->rq_client = cl;
- request->rq_connection = ptlrpc_connection_addref(conn);
-
- INIT_LIST_HEAD(&request->rq_list);
- INIT_LIST_HEAD(&request->rq_multi);
- /* this will be dec()d once in req_finished, once in free_committed */
- atomic_set(&request->rq_refcount, 2);
-
- spin_lock(&conn->c_lock);
- request->rq_xid = HTON__u32(++conn->c_xid_out);
- spin_unlock(&conn->c_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->type = HTON__u32(PTL_RPC_MSG_REQUEST);
-
- RETURN(request);
-}
-struct ptlrpc_request *ptlrpc_prep_req2(struct lustre_handle *conn,
- int opcode, int count, int *lengths,
- char **bufs)
-{
- struct client_obd *clobd;
- struct ptlrpc_request *req;
- struct obd_export *export;
-
- export = class_conn2export(conn);
- if (!export) {
- LBUG();
- CERROR("NOT connected\n");
- return NULL;
- }
-
- clobd = &export->exp_obd->u.cli;
- req = ptlrpc_prep_req(clobd->cl_client, clobd->cl_conn,
- opcode, count, lengths, bufs);
- ptlrpc_hdl2req(req, &clobd->cl_exporth);
- return req;
-}
-
-void ptlrpc_req_finished(struct ptlrpc_request *request)
-{
- if (request == NULL)
- return;
-
- if (request->rq_repmsg != NULL) {
- OBD_FREE(request->rq_repmsg, request->rq_replen);
- request->rq_repmsg = NULL;
- request->rq_reply_md.start = NULL;
- }
-
- if (atomic_dec_and_test(&request->rq_refcount))
- ptlrpc_free_req(request);
-}
-
-void ptlrpc_free_req(struct ptlrpc_request *request)
-{
- ENTRY;
- if (request == NULL) {
- EXIT;
- return;
- }
-
- if (request->rq_repmsg != NULL)
- OBD_FREE(request->rq_repmsg, request->rq_replen);
- if (request->rq_reqmsg != NULL)
- OBD_FREE(request->rq_reqmsg, request->rq_reqlen);
-
- if (request->rq_client) {
- spin_lock(&request->rq_client->cli_lock);
- list_del_init(&request->rq_list);
- spin_unlock(&request->rq_client->cli_lock);
- }
-
- ptlrpc_put_connection(request->rq_connection);
- list_del(&request->rq_multi);
- OBD_FREE(request, sizeof(*request));
- EXIT;
-}
-
-static int ptlrpc_check_reply(struct ptlrpc_request *req)
-{
- int rc = 0;
-
- 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 0
- if (req->rq_flags & PTL_RPC_FL_RESEND) {
- if (l_killable_pending(current)) {
- CERROR("-- INTR --\n");
- req->rq_flags |= PTL_RPC_FL_INTR;
- GOTO(out, rc = 1);
- }
- CERROR("-- RESEND --\n");
- GOTO(out, rc = 1);
- }
-#endif
-
- if (req->rq_flags & PTL_RPC_FL_RECOVERY) {
- CERROR("-- RESTART --\n");
- GOTO(out, rc = 1);
- }
-
- if (req->rq_flags & PTL_RPC_FL_TIMEOUT && l_killable_pending(current)) {
- req->rq_flags |= PTL_RPC_FL_INTR;
- GOTO(out, rc = 1);
- }
-
- if (req->rq_timeout &&
- (CURRENT_TIME - req->rq_time >= req->rq_timeout)) {
- CERROR("-- REQ TIMEOUT ON CONNID %d XID %Ld --\n",
- req->rq_connid, (unsigned long long)req->rq_xid);
- /* clear the timeout */
- req->rq_timeout = 0;
- req->rq_connection->c_level = LUSTRE_CONN_RECOVD;
- req->rq_flags |= PTL_RPC_FL_TIMEOUT;
- if (req->rq_client && req->rq_client->cli_recovd)
- recovd_cli_fail(req->rq_client);
- if (req->rq_level < LUSTRE_CONN_FULL) {
- rc = 1;
- } else if (l_killable_pending(current)) {
- req->rq_flags |= PTL_RPC_FL_INTR;
- rc = 1;
- } else {
- rc = 0;
- }
- GOTO(out, rc);
- }
-
- out:
- CDEBUG(D_NET, "req = %p, rc = %d\n", req, rc);
- return rc;
-}
-
-int ptlrpc_check_status(struct ptlrpc_request *req, int err)
-{
- ENTRY;
-
- if (err != 0) {
- CERROR("err is %d\n", err);
- RETURN(err);
- }
-
- if (req == NULL) {
- CERROR("req == NULL\n");
- RETURN(-ENOMEM);
- }
-
- if (req->rq_repmsg == NULL) {
- CERROR("req->rq_repmsg == NULL\n");
- RETURN(-ENOMEM);
- }
-
- err = req->rq_repmsg->status;
- if (req->rq_repmsg->type == NTOH__u32(PTL_RPC_MSG_ERR)) {
- CERROR("req->rq_repmsg->type == PTL_RPC_MSG_ERR\n");
- RETURN(err ? err : -EINVAL);
- }
-
- if (err != 0) {
- if (err < 0)
- CERROR("req->rq_repmsg->status is %d\n", err);
- else
- CDEBUG(D_INFO, "req->rq_repmsg->status is %d\n", err);
- /* XXX: translate this error from net to host */
- RETURN(err);
- }
-
- RETURN(0);
-}
-
-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 lock cli */
-void ptlrpc_free_committed(struct ptlrpc_client *cli)
-{
- struct list_head *tmp, *saved;
- struct ptlrpc_request *req;
-
- list_for_each_safe(tmp, saved, &cli->cli_sending_head) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
-
- if ( (req->rq_flags & PTL_RPC_FL_REPLAY) ) {
- CDEBUG(D_INFO, "Retaining request %Ld for replay\n",
- req->rq_xid);
- continue;
- }
-
- /* not yet committed */
- if (req->rq_transno > cli->cli_last_committed)
- break;
-
- CDEBUG(D_INFO, "Marking request xid %Ld as committed ("
- "transno=%Lu, last_committed=%Lu\n",
- (long long)req->rq_xid, (long long)req->rq_transno,
- (long long)cli->cli_last_committed);
- if (atomic_dec_and_test(&req->rq_refcount)) {
- /* we do this to prevent free_req deadlock */
- list_del_init(&req->rq_list);
- req->rq_client = NULL;
- ptlrpc_free_req(req);
- } else {
- list_del_init(&req->rq_list);
- list_add(&req->rq_list, &cli->cli_dying_head);
- }
- }
-
- EXIT;
- return;
-}
-
-void ptlrpc_cleanup_client(struct ptlrpc_client *cli)
-{
- struct list_head *tmp, *saved;
- struct ptlrpc_request *req;
- ENTRY;
-
- spin_lock(&cli->cli_lock);
- list_for_each_safe(tmp, saved, &cli->cli_sending_head) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
- CDEBUG(D_INFO, "Cleaning req %p from sending list.\n", req);
- list_del_init(&req->rq_list);
- req->rq_client = NULL;
- ptlrpc_free_req(req);
- }
- list_for_each_safe(tmp, saved, &cli->cli_dying_head) {
- req = list_entry(tmp, struct ptlrpc_request, rq_list);
- CERROR("Request %p is on the dying list at cleanup!\n", req);
- list_del_init(&req->rq_list);
- req->rq_client = NULL;
- ptlrpc_free_req(req);
- }
- spin_unlock(&cli->cli_lock);
-
- EXIT;
- return;
-}
-
-void ptlrpc_continue_req(struct ptlrpc_request *req)
-{
- ENTRY;
- CDEBUG(D_INODE, "continue delayed request %Ld opc %d\n",
- req->rq_xid, req->rq_reqmsg->opc);
- wake_up(&req->rq_wait_for_rep);
- EXIT;
-}
-
-void ptlrpc_resend_req(struct ptlrpc_request *req)
-{
- ENTRY;
- CDEBUG(D_INODE, "resend request %Ld, opc %d\n",
- req->rq_xid, req->rq_reqmsg->opc);
- 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;
- CDEBUG(D_INODE, "restart completed request %Ld, opc %d\n",
- req->rq_xid, req->rq_reqmsg->opc);
- req->rq_status = -ERESTARTSYS;
- req->rq_flags |= PTL_RPC_FL_RECOVERY;
- 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;
- req->rq_timeout = 0;
- req->rq_connection->c_level = LUSTRE_CONN_RECOVD;
- req->rq_flags |= PTL_RPC_FL_TIMEOUT;
- /* Activate the recovd for this client, if there is one. */
- if (req->rq_client && req->rq_client->cli_recovd)
- recovd_cli_fail(req->rq_client);
-
- /* 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);
- 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 */
-}
-
-int ptlrpc_queue_wait(struct ptlrpc_request *req)
-{
- int rc = 0;
- struct l_wait_info lwi;
- struct ptlrpc_client *cli = req->rq_client;
- ENTRY;
-
- init_waitqueue_head(&req->rq_wait_for_rep);
- CDEBUG(D_NET, "subsys: %s req %Ld opc %d level %d, conn level %d\n",
- cli->cli_name, req->rq_xid, req->rq_reqmsg->opc, req->rq_level,
- req->rq_connection->c_level);
-
- /* XXX probably both an import and connection level are needed */
- if (req->rq_level > req->rq_connection->c_level) {
- CERROR("process %d waiting for recovery (%d > %d)\n",
- current->pid, req->rq_level, req->rq_connection->c_level);
-
- spin_lock(&cli->cli_lock);
- list_del_init(&req->rq_list);
- list_add_tail(&req->rq_list, &cli->cli_delayed_head);
- spin_unlock(&cli->cli_lock);
-
-#warning shaver: what happens when we get interrupted during this wait?
- lwi = LWI_INTR(SIGTERM | SIGKILL | SIGINT, NULL, NULL);
- l_wait_event(req->rq_wait_for_rep,
- req->rq_level <= req->rq_connection->c_level,
- &lwi);
-
- spin_lock(&cli->cli_lock);
- list_del_init(&req->rq_list);
- spin_unlock(&cli->cli_lock);
-
- CERROR("process %d resumed\n", current->pid);
- }
- resend:
- req->rq_time = CURRENT_TIME;
- req->rq_timeout = 100;
- rc = ptl_send_rpc(req);
- if (rc) {
- CERROR("error %d, opcode %d\n", rc, req->rq_reqmsg->opc);
- if ( rc > 0 )
- rc = -rc;
- ptlrpc_cleanup_request_buf(req);
- up(&cli->cli_rpc_sem);
- RETURN(-rc);
- }
-
- spin_lock(&cli->cli_lock);
- list_del_init(&req->rq_list);
- list_add_tail(&req->rq_list, &cli->cli_sending_head);
- spin_unlock(&cli->cli_lock);
-
- CDEBUG(D_OTHER, "-- sleeping\n");
- lwi = LWI_TIMEOUT_INTR(req->rq_timeout * HZ, expired_request,
- SIGKILL | SIGTERM | SIGINT, interrupted_request,
- req);
- l_wait_event(req->rq_wait_for_rep, ptlrpc_check_reply(req), &lwi);
- CDEBUG(D_OTHER, "-- done\n");
-
- /* 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;
- goto resend;
- }
-
- up(&cli->cli_rpc_sem);
- 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);
- }
- CDEBUG(D_NET, "got rep %Ld\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);
-
- spin_lock(&cli->cli_lock);
- cli->cli_last_xid = req->rq_repmsg->last_xid;
- cli->cli_last_committed = req->rq_repmsg->last_committed;
- ptlrpc_free_committed(cli);
- spin_unlock(&cli->cli_lock);
-
- EXIT;
- out:
- return rc;
-}
-
-int ptlrpc_replay_req(struct ptlrpc_request *req)
-{
- int rc = 0;
- struct ptlrpc_client *cli = req->rq_client;
- struct l_wait_info lwi = LWI_INTR(SIGKILL|SIGTERM|SIGINT, NULL, NULL);
- ENTRY;
-
- init_waitqueue_head(&req->rq_wait_for_rep);
- CDEBUG(D_NET, "req %Ld opc %d level %d, conn level %d\n",
- req->rq_xid, req->rq_reqmsg->opc, req->rq_level,
- req->rq_connection->c_level);
-
- req->rq_time = CURRENT_TIME;
- req->rq_timeout = 100;
- 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);
- RETURN(-rc);
- }
-
- CDEBUG(D_OTHER, "-- sleeping\n");
- 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 %Ld\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);
- else {
- CERROR("recovery failed: ");
- CERROR("req %Ld opc %d level %d, conn level %d\n",
- req->rq_xid, req->rq_reqmsg->opc, req->rq_level,
- req->rq_connection->c_level);
- LBUG();
- }
-
- out:
- 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/lustre_net.h>
-
-static spinlock_t conn_lock;
-static struct list_head conn_list;
-static struct list_head conn_unused_list;
-
-struct ptlrpc_connection *ptlrpc_get_connection(struct lustre_peer *peer)
-{
- struct list_head *tmp, *pos;
- struct ptlrpc_connection *c;
- ENTRY;
-
- 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) {
- 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) {
- 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_level = LUSTRE_CONN_NEW;
- c->c_xid_in = 1;
- c->c_xid_out = 1;
- c->c_generation = 1;
- c->c_epoch = 1;
- c->c_bootcount = 0;
- 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;
-
- CDEBUG(D_INFO, "connection=%p\n", c);
- if (atomic_dec_and_test(&c->c_refcount)) {
- 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)
- CDEBUG(D_INFO, "refcount < 0 for connection %p!\n", c);
-
- RETURN(rc);
-}
-
-struct ptlrpc_connection *ptlrpc_connection_addref(struct ptlrpc_connection *c)
-{
- ENTRY;
- CDEBUG(D_INFO, "connection=%p\n", c);
- 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 has refcount %d at cleanup (nid=%lu)!\n",
- c, 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:
- *
- * 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/kmod.h>
-#include <linux/lustre_lite.h>
-#include <linux/lustre_ha.h>
-
-static int connmgr_unpack_body(struct ptlrpc_request *req)
-{
- struct connmgr_body *b = lustre_msg_buf(req->rq_repmsg, 0);
- if (b == NULL) {
- LBUG();
- RETURN(-EINVAL);
- }
-
- b->generation = NTOH__u32(b->generation);
-
- return 0;
-}
-
-int connmgr_connect(struct recovd_obd *recovd, struct ptlrpc_connection *conn)
-{
- struct ptlrpc_request *req;
- struct ptlrpc_client *cl;
- struct connmgr_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- if (!recovd) {
- CERROR("no manager\n");
- LBUG();
- }
- cl = recovd->recovd_client;
-
- req = ptlrpc_prep_req(cl, conn, CONNMGR_CONNECT, 1, &size, NULL);
- if (!req)
- GOTO(out, rc = -ENOMEM);
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- body->generation = HTON__u32(conn->c_generation);
- body->conn = (__u64)(unsigned long)conn;
- body->conn_token = conn->c_token;
- strncpy(body->conn_uuid, conn->c_local_uuid, sizeof(body->conn_uuid));
-
- req->rq_replen = lustre_msg_size(1, &size);
- req->rq_level = LUSTRE_CONN_NEW;
-
- rc = ptlrpc_queue_wait(req);
- rc = ptlrpc_check_status(req, rc);
- if (!rc) {
- rc = connmgr_unpack_body(req);
- if (rc)
- GOTO(out_free, rc);
- body = lustre_msg_buf(req->rq_repmsg, 0);
- CDEBUG(D_NET, "remote generation: %o\n", body->generation);
- conn->c_level = LUSTRE_CONN_CON;
- conn->c_remote_conn = body->conn;
- conn->c_remote_token = body->conn_token;
- strncpy(conn->c_remote_uuid, body->conn_uuid,
- sizeof(conn->c_remote_uuid));
- }
-
- EXIT;
- out_free:
- ptlrpc_free_req(req);
- out:
- return rc;
-}
-
-static int connmgr_handle_connect(struct ptlrpc_request *req)
-{
- struct connmgr_body *body;
- int rc, size = sizeof(*body);
- ENTRY;
-
- rc = lustre_pack_msg(1, &size, NULL, &req->rq_replen, &req->rq_repmsg);
- if (rc) {
- CERROR("connmgr: out of memory\n");
- req->rq_status = -ENOMEM;
- RETURN(0);
- }
-
- body = lustre_msg_buf(req->rq_reqmsg, 0);
- connmgr_unpack_body(req);
-
- req->rq_connection->c_remote_conn = body->conn;
- req->rq_connection->c_remote_token = body->conn_token;
- strncpy(req->rq_connection->c_remote_uuid, body->conn_uuid,
- sizeof(req->rq_connection->c_remote_uuid));
-
- CERROR("incoming generation %d\n", body->generation);
- body = lustre_msg_buf(req->rq_repmsg, 0);
- body->generation = 4711;
- body->conn = (__u64)(unsigned long)req->rq_connection;
- body->conn_token = req->rq_connection->c_token;
-
- req->rq_connection->c_level = LUSTRE_CONN_CON;
- RETURN(0);
-}
-
-int connmgr_handle(struct ptlrpc_request *req)
-{
- int rc;
- ENTRY;
-
- rc = lustre_unpack_msg(req->rq_reqmsg, req->rq_reqlen);
- if (rc) {
- CERROR("Invalid request\n");
- GOTO(out, rc);
- }
-
- if (req->rq_reqmsg->type != NTOH__u32(PTL_RPC_MSG_REQUEST)) {
- CERROR("wrong packet type sent %d\n",
- req->rq_reqmsg->type);
- GOTO(out, rc = -EINVAL);
- }
-
- switch (req->rq_reqmsg->opc) {
- case CONNMGR_CONNECT:
- CDEBUG(D_INODE, "connmgr connect\n");
- rc = connmgr_handle_connect(req);
- break;
-
- default:
- rc = ptlrpc_error(req->rq_svc, req);
- RETURN(rc);
- }
-
- EXIT;
-out:
- if (rc) {
- ptlrpc_error(req->rq_svc, req);
- } else {
- CDEBUG(D_NET, "sending reply\n");
- ptlrpc_reply(req->rq_svc, req);
- }
-
- 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.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, *qswnal_nip = NULL;
-
-/*
- * Free the packet when it has gone out
- */
-static int request_out_callback(ptl_event_t *ev)
-{
- ENTRY;
-
- LASSERT ((ev->mem_desc.options & PTL_MD_IOV) == 0); /* requests always contiguous */
-
- if (ev->type != PTL_EVENT_SENT) {
- // XXX make sure we understand all events, including ACK's
- CERROR("Unknown event %d\n", ev->type);
- LBUG();
- }
-
- RETURN(1);
-}
-
-
-/*
- * Free the packet when it has gone out
- */
-static int reply_out_callback(ptl_event_t *ev)
-{
- ENTRY;
-
- LASSERT ((ev->mem_desc.options & PTL_MD_IOV) == 0); /* replies always contiguous */
-
- 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;
-
- LASSERT ((ev->mem_desc.options & PTL_MD_IOV) == 0); /* replies always contiguous */
-
- 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_service *service = ev->mem_desc.user_ptr;
-
- LASSERT ((ev->mem_desc.options & PTL_MD_IOV) == 0); /* requests always contiguous */
-
- if (ev->rlength != ev->mlength)
- CERROR("Warning: Possibly truncated rpc (%d/%d)\n",
- ev->mlength, ev->rlength);
-
- if (ev->type == PTL_EVENT_PUT)
- wake_up(&service->srv_waitq);
- else
- CERROR("Unexpected event type: %d\n", ev->type);
-
- 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;
-
- /* 1 fragment for each page always */
- LASSERT (ev->mem_desc.niov == desc->b_page_count);
-
- if (ev->type == PTL_EVENT_SENT) {
- CDEBUG(D_NET, "got SENT event\n");
- } else if (ev->type == PTL_EVENT_ACK) {
- CDEBUG(D_NET, "got ACK event\n");
-
- list_for_each_safe(tmp, next, &desc->b_page_list) {
- bulk = list_entry(tmp, struct ptlrpc_bulk_page, b_link);
-
- if (bulk->b_cb != NULL)
- bulk->b_cb(bulk);
- }
- desc->b_flags |= PTL_BULK_FL_SENT;
- wake_up(&desc->b_waitq);
- if (desc->b_cb != NULL)
- desc->b_cb(desc, desc->b_cb_data);
- } else {
- CERROR("Unexpected event type!\n");
- LBUG();
- }
-
- RETURN(1);
-}
-
-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->b_page_count);
-
- list_for_each_safe (tmp, next, &desc->b_page_list) {
- bulk = list_entry(tmp, struct ptlrpc_bulk_page, b_link);
-
- total += bulk->b_buflen;
-
- if (bulk->b_cb != NULL)
- bulk->b_cb(bulk);
- }
-
- LASSERT (ev->mem_desc.length == total);
-
- desc->b_flags |= PTL_BULK_FL_RCVD;
- wake_up(&desc->b_waitq);
- if (desc->b_cb != NULL)
- desc->b_cb(desc, desc->b_cb_data);
- } else {
- CERROR("Unexpected event type!\n");
- LBUG();
- }
-
- RETURN(1);
-}
-
-int ptlrpc_init_portals(void)
-{
- int rc;
- ptl_handle_ni_t ni;
-
- socknal_nip = inter_module_get_request("ksocknal_ni", "ksocknal");
- qswnal_nip = inter_module_get_request("kqswnal_ni", "kqswnal");
- if (socknal_nip == NULL && qswnal_nip == NULL) {
- CERROR("get_ni failed: is a NAL module loaded?\n");
- return -EIO;
- }
-
- /* Use the qswnal if it's there */
- if (qswnal_nip != NULL)
- ni = *qswnal_nip;
- else
- ni = *socknal_nip;
-
- 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");
-}
+++ /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>
-
-extern ptl_handle_eq_t request_out_eq, reply_in_eq, reply_out_eq,
- bulk_source_eq, bulk_sink_eq;
-static ptl_process_id_t local_id = {PTL_NID_ANY, PTL_PID_ANY};
-
-int ptlrpc_check_bulk_sent(struct ptlrpc_bulk_desc *desc)
-{
- ENTRY;
-
- if (desc->b_flags & PTL_BULK_FL_SENT)
- RETURN(1);
-
- if (l_killable_pending(current)) {
- desc->b_flags |= PTL_RPC_FL_INTR;
- RETURN(1);
- }
-
- CDEBUG(D_NET, "no event yet\n");
- RETURN(0);
-}
-
-int ptlrpc_check_bulk_received(struct ptlrpc_bulk_desc *desc)
-{
- ENTRY;
-
- if (desc->b_flags & PTL_BULK_FL_RCVD)
- RETURN(1);
-
- if (l_killable_pending(current)) {
- desc->b_flags |= PTL_RPC_FL_INTR;
- RETURN(1);
- }
-
- CDEBUG(D_NET, "no event yet\n");
- RETURN(0);
-}
-
-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;
- ptl_ack_req_t ack;
-
- request->rq_req_md.user_ptr = request;
-
- switch (request->rq_type) {
- case PTL_RPC_TYPE_REQUEST:
- request->rq_req_md.start = request->rq_reqmsg;
- request->rq_req_md.length = request->rq_reqlen;
- request->rq_req_md.eventq = request_out_eq;
- request->rq_req_md.threshold = 1;
- ack = PTL_NOACK_REQ;
- break;
- case PTL_RPC_TYPE_REPLY:
- request->rq_req_md.start = request->rq_repmsg;
- request->rq_req_md.length = request->rq_replen;
- request->rq_req_md.eventq = reply_out_eq;
- request->rq_req_md.threshold = 1;
- ack = PTL_NOACK_REQ;
- break;
- default:
- LBUG();
- return -1; /* notreached */
- }
- 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);
- //CERROR("MDBind (outgoing req/rep/bulk): %Lu\n", (__u64)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 %Ld\n",
- request->rq_req_md.length, portal, request->rq_xid);
-
- rc = PtlPut(md_h, ack, remote_id, portal, 0, request->rq_xid,
- 0, 0);
- if (rc != PTL_OK) {
- CERROR("PtlPut(%Lu, %d, %Ld) 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->b_page_count <= sizeof (desc->b_iov)/sizeof (struct iovec))
- return (desc->b_iov);
-
- OBD_ALLOC (iov, desc->b_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->b_page_count <= sizeof (desc->b_iov)/sizeof (struct iovec))
- return;
-
- OBD_FREE (iov, desc->b_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->b_md.start = iov;
- desc->b_md.niov = 0;
- desc->b_md.length = 0;
- desc->b_md.eventq = bulk_source_eq;
- desc->b_md.threshold = 2; /* SENT and ACK */
- desc->b_md.options = PTL_MD_OP_PUT | PTL_MD_IOV;
- desc->b_md.user_ptr = desc;
-
- list_for_each_safe(tmp, next, &desc->b_page_list) {
- struct ptlrpc_bulk_page *bulk;
- bulk = list_entry(tmp, struct ptlrpc_bulk_page, b_link);
-
- LASSERT (desc->b_md.niov < desc->b_page_count);
-
- if (desc->b_md.niov == 0)
- xid = bulk->b_xid;
- LASSERT (xid == bulk->b_xid); /* should all be the same */
-
- iov[desc->b_md.niov].iov_base = bulk->b_buf;
- iov[desc->b_md.niov].iov_len = bulk->b_buflen;
- desc->b_md.niov++;
- desc->b_md.length += bulk->b_buflen;
- }
-
- LASSERT (desc->b_md.niov == desc->b_page_count);
- LASSERT (desc->b_md.niov != 0);
-
- rc = PtlMDBind(desc->b_connection->c_peer.peer_ni, desc->b_md,
- &desc->b_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->b_connection->c_peer.peer_nid;
- remote_id.pid = 0;
-
- CDEBUG(D_NET, "Sending %u pages %u bytes to portal %d nid %Lx pid %d xid %d\n",
- desc->b_md.niov, desc->b_md.length,
- desc->b_portal, remote_id.nid, remote_id.pid, xid);
-
- rc = PtlPut(desc->b_md_h, PTL_ACK_REQ, remote_id,
- desc->b_portal, 0, xid, 0, 0);
- if (rc != PTL_OK) {
- CERROR("PtlPut(%Lu, %d, %d) failed: %d\n",
- remote_id.nid, desc->b_portal, xid, rc);
- PtlMDUnlink(desc->b_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;
- ENTRY;
-
- iov = ptlrpc_get_bulk_iov (desc);
- if (iov == NULL)
- return (-ENOMEM);
-
- desc->b_md.start = iov;
- desc->b_md.niov = 0;
- desc->b_md.length = 0;
- desc->b_md.threshold = 1;
- desc->b_md.options = PTL_MD_OP_PUT | PTL_MD_IOV;
- desc->b_md.user_ptr = desc;
- desc->b_md.eventq = bulk_sink_eq;
-
- list_for_each_safe(tmp, next, &desc->b_page_list) {
- struct ptlrpc_bulk_page *bulk;
- bulk = list_entry(tmp, struct ptlrpc_bulk_page, b_link);
-
- LASSERT (desc->b_md.niov < desc->b_page_count);
-
- if (desc->b_md.niov == 0)
- xid = bulk->b_xid;
- LASSERT (xid == bulk->b_xid); /* should all be the same */
-
- iov[desc->b_md.niov].iov_base = bulk->b_buf;
- iov[desc->b_md.niov].iov_len = bulk->b_buflen;
- desc->b_md.niov++;
- desc->b_md.length += bulk->b_buflen;
- }
-
- LASSERT (desc->b_md.niov == desc->b_page_count);
- LASSERT (desc->b_md.niov != 0);
-
- rc = PtlMEAttach(desc->b_connection->c_peer.peer_ni,
- desc->b_portal, local_id, xid, 0,
- PTL_UNLINK, PTL_INS_AFTER, &desc->b_me_h);
-
- ptlrpc_put_bulk_iov (desc, iov);
-
- if (rc != PTL_OK) {
- CERROR("PtlMEAttach failed: %d\n", rc);
- LBUG();
- GOTO(cleanup, rc);
- }
-
- rc = PtlMDAttach(desc->b_me_h, desc->b_md, PTL_UNLINK,
- &desc->b_md_h);
- if (rc != PTL_OK) {
- CERROR("PtlMDAttach failed: %d\n", rc);
- LBUG();
- GOTO(cleanup, rc);
- }
-
- CDEBUG(D_NET, "Setup bulk sink buffers: %u pages %u bytes, xid %u, "
- "portal %u\n", desc->b_md.niov, desc->b_md.length,
- xid, desc->b_portal);
-
- RETURN(0);
-
- cleanup:
- 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->b_md_h);
- PtlMEUnlink(desc->b_me_h);
-
- return 0;
-}
-
-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 */
- req->rq_type = PTL_RPC_TYPE_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);
- req->rq_reqmsg->type = HTON__u32(req->rq_type);
- 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_repmsg->type = HTON__u32(PTL_RPC_MSG_ERR);
-
- rc = ptlrpc_reply(svc, req);
- RETURN(rc);
-}
-
-
-int ptl_send_rpc(struct ptlrpc_request *request)
-{
- int rc;
- char *repbuf;
-
- ENTRY;
-
- if (NTOH__u32(request->rq_reqmsg->type) != PTL_RPC_MSG_REQUEST) {
- CERROR("wrong packet type sent %d\n",
- NTOH__u32(request->rq_reqmsg->type));
- LBUG();
- RETURN(EINVAL);
- }
- if (request->rq_replen == 0) {
- CERROR("request->rq_replen is 0!\n");
- RETURN(EINVAL);
- }
-
- /* request->rq_repmsg is set only when the reply comes in, in
- * client_packet_callback() */
- if (request->rq_reply_md.start)
- OBD_FREE(request->rq_reply_md.start, request->rq_replen);
-
- OBD_ALLOC(repbuf, request->rq_replen);
- if (!repbuf) {
- LBUG();
- RETURN(ENOMEM);
- }
-
- down(&request->rq_client->cli_rpc_sem);
-
- rc = PtlMEAttach(request->rq_connection->c_peer.peer_ni,
- request->rq_client->cli_reply_portal,
- local_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_type = PTL_RPC_TYPE_REQUEST;
- 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, &request->rq_reply_md_h);
- if (rc != PTL_OK) {
- CERROR("PtlMDAttach failed: %d\n", rc);
- LBUG();
- GOTO(cleanup2, rc);
- }
-
- CDEBUG(D_NET, "Setup reply buffer: %u bytes, xid %Lu, portal %u\n",
- request->rq_replen, request->rq_xid,
- request->rq_client->cli_reply_portal);
-
- rc = ptl_send_buf(request, request->rq_connection,
- request->rq_client->cli_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_service *service, int i)
-{
- int rc;
- ptl_md_t dummy;
- ptl_handle_md_t md_h;
-
- /* Attach the leading ME on which we build the ring */
- rc = PtlMEAttach(service->srv_self.peer_ni, service->srv_req_portal,
- local_id, 0, ~0, PTL_RETAIN, PTL_INS_BEFORE,
- &(service->srv_me_h[i]));
- if (rc != PTL_OK) {
- CERROR("PtlMEAttach failed: %d\n", rc);
- LBUG();
- }
-
- if (service->srv_ref_count[i])
- LBUG();
-
- dummy.start = service->srv_buf[i];
- dummy.length = service->srv_buf_size;
- dummy.max_offset = service->srv_buf_size;
- dummy.threshold = PTL_MD_THRESH_INF;
- dummy.options = PTL_MD_OP_PUT | PTL_MD_AUTO_UNLINK;
- dummy.user_ptr = service;
- dummy.eventq = service->srv_eq_h;
- dummy.max_offset = service->srv_buf_size;
-
- rc = PtlMDAttach(service->srv_me_h[i], dummy, PTL_UNLINK, &md_h);
- if (rc != PTL_OK) {
- /* cleanup */
- CERROR("PtlMDAttach failed: %d\n", rc);
- LBUG();
- }
-}
-
-/* ptl_handled_rpc() should be called by the sleeping process once
- * it finishes processing an event. This ensures the ref count is
- * decremented and that the rpc ring buffer cycles properly.
- */
-int ptl_handled_rpc(struct ptlrpc_service *service, void *start)
-{
- int index;
-
- spin_lock(&service->srv_lock);
- for (index = 0; index < service->srv_ring_length; index++)
- if (service->srv_buf[index] == start)
- break;
-
- if (index == service->srv_ring_length)
- LBUG();
-
- CDEBUG(D_INFO, "MD index=%d Ref Count=%d\n", index,
- service->srv_ref_count[index]);
- service->srv_ref_count[index]--;
-
- if (service->srv_ref_count[index] < 0)
- LBUG();
-
- if (service->srv_ref_count[index] == 0 &&
- !ptl_is_valid_handle(&(service->srv_me_h[index]))) {
- CDEBUG(D_NET, "relinking %d\n", index);
- ptlrpc_link_svc_me(service, index);
- }
-
- spin_unlock(&service->srv_lock);
- return 0;
-}
+++ /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_CLASS
-
-#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;
-
- 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 (requested %d, count is "
- "%d)!\n", n, m->bufcount);
- LBUG();
- return NULL;
- }
-
- if (m->buflens[n] == 0)
- 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/kmod.h>
-#include <linux/lustre_lite.h>
-#include <linux/lustre_ha.h>
-
-struct recovd_obd *ptlrpc_connmgr;
-
-void recovd_cli_manage(struct recovd_obd *recovd, struct ptlrpc_client *cli)
-{
- ENTRY;
- cli->cli_recovd = recovd;
- spin_lock(&recovd->recovd_lock);
- list_add(&cli->cli_ha_item, &recovd->recovd_clients_lh);
- spin_unlock(&recovd->recovd_lock);
- EXIT;
-}
-
-void recovd_cli_fail(struct ptlrpc_client *cli)
-{
- ENTRY;
- spin_lock(&cli->cli_recovd->recovd_lock);
- cli->cli_recovd->recovd_flags |= RECOVD_FAIL;
- cli->cli_recovd->recovd_wakeup_flag = 1;
- list_del(&cli->cli_ha_item);
- list_add(&cli->cli_ha_item, &cli->cli_recovd->recovd_troubled_lh);
- spin_unlock(&cli->cli_recovd->recovd_lock);
- wake_up(&cli->cli_recovd->recovd_waitq);
- EXIT;
-}
-
-/* this function must be called with cli->cli_lock held */
-void recovd_cli_fixed(struct ptlrpc_client *cli)
-{
- ENTRY;
- list_del(&cli->cli_ha_item);
- list_add(&cli->cli_ha_item, &cli->cli_recovd->recovd_clients_lh);
- EXIT;
-}
-
-
-static int recovd_upcall(void)
-{
- char *argv[2];
- char *envp[3];
-
- argv[0] = "/usr/src/obd/utils/ha_assist.sh";
- argv[1] = NULL;
-
- envp [0] = "HOME=/";
- envp [1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
- envp [2] = NULL;
-
- return call_usermodehelper(argv[0], argv, envp);
-}
-
-static int recovd_check_event(struct recovd_obd *recovd)
-{
- int rc = 0;
- ENTRY;
-
- spin_lock(&recovd->recovd_lock);
-
- recovd->recovd_waketime = CURRENT_TIME;
- if (recovd->recovd_timeout)
- schedule_timeout(recovd->recovd_timeout);
-
- if (recovd->recovd_wakeup_flag) {
- CERROR("service woken\n");
- GOTO(out, rc = 1);
- }
-
- if (recovd->recovd_timeout &&
- CURRENT_TIME > recovd->recovd_waketime + recovd->recovd_timeout) {
- recovd->recovd_flags |= RECOVD_TIMEOUT;
- CERROR("timeout\n");
- GOTO(out, rc = 1);
- }
-
- if (recovd->recovd_flags & RECOVD_STOPPING) {
- CERROR("recovd stopping\n");
- rc = 1;
- }
-
- out:
- recovd->recovd_wakeup_flag = 0;
- spin_unlock(&recovd->recovd_lock);
- RETURN(rc);
-}
-
-static int recovd_handle_event(struct recovd_obd *recovd)
-{
- ENTRY;
-
- if (!(recovd->recovd_flags & RECOVD_UPCALL_WAIT) &&
- recovd->recovd_flags & RECOVD_FAIL) {
-
- CERROR("client in trouble: flags -> UPCALL_WAITING\n");
- recovd->recovd_flags |= RECOVD_UPCALL_WAIT;
-
- recovd_upcall();
- recovd->recovd_waketime = CURRENT_TIME;
- recovd->recovd_timeout = 10 * HZ;
- schedule_timeout(recovd->recovd_timeout);
- }
-
- if (recovd->recovd_flags & RECOVD_TIMEOUT) {
- CERROR("timeout - no news from upcall?\n");
- recovd->recovd_flags &= ~RECOVD_TIMEOUT;
- }
-
- if (recovd->recovd_flags & RECOVD_UPCALL_ANSWER) {
- CERROR("UPCALL_WAITING: upcall answer\n");
-
- while (!list_empty(&recovd->recovd_troubled_lh)) {
- struct ptlrpc_client *cli =
- list_entry(recovd->recovd_troubled_lh.next,
- struct ptlrpc_client, cli_ha_item);
-
- list_del(&cli->cli_ha_item);
- if (cli->cli_recover) {
- spin_unlock(&recovd->recovd_lock);
- cli->cli_recover(cli);
- spin_lock(&recovd->recovd_lock);
- }
- }
-
- recovd->recovd_timeout = 0;
- recovd->recovd_flags = RECOVD_IDLE;
- }
-
- RETURN(0);
-}
-
-static int recovd_main(void *arg)
-{
- struct recovd_obd *recovd = (struct recovd_obd *)arg;
-
- ENTRY;
-
- lock_kernel();
- daemonize();
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
-
- sprintf(current->comm, "lustre_recovd");
-
- /* Record that the thread is running */
- recovd->recovd_thread = current;
- recovd->recovd_flags = RECOVD_IDLE;
- wake_up(&recovd->recovd_ctl_waitq);
-
- /* And now, loop forever on requests */
- while (1) {
- wait_event(recovd->recovd_waitq, recovd_check_event(recovd));
-
- spin_lock(&recovd->recovd_lock);
- if (recovd->recovd_flags & RECOVD_STOPPING) {
- spin_unlock(&recovd->recovd_lock);
- CERROR("lustre_recovd stopping\n");
- EXIT;
- break;
- }
-
- recovd_handle_event(recovd);
- spin_unlock(&recovd->recovd_lock);
- }
-
- recovd->recovd_thread = NULL;
- recovd->recovd_flags = RECOVD_STOPPED;
- wake_up(&recovd->recovd_ctl_waitq);
- CDEBUG(D_NET, "mgr exiting process %d\n", current->pid);
- RETURN(0);
-}
-
-int recovd_setup(struct recovd_obd *recovd)
-{
- int rc;
- ENTRY;
-
- INIT_LIST_HEAD(&recovd->recovd_clients_lh);
- INIT_LIST_HEAD(&recovd->recovd_troubled_lh);
- 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_flags & RECOVD_IDLE);
-
- RETURN(0);
-}
-
-int recovd_cleanup(struct recovd_obd *recovd)
-{
- spin_lock(&recovd->recovd_lock);
- recovd->recovd_flags = RECOVD_STOPPING;
- wake_up(&recovd->recovd_waitq);
- spin_unlock(&recovd->recovd_lock);
-
- wait_event(recovd->recovd_ctl_waitq,
- (recovd->recovd_flags & RECOVD_STOPPED));
- 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.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/init.h>
-
-extern int ptlrpc_init_portals(void);
-extern void ptlrpc_exit_portals(void);
-
-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));
-
- OBD_ALLOC(recovd->recovd_client, sizeof(*recovd->recovd_client));
- if (!recovd)
- GOTO(err_dec, err = -ENOMEM);
-
- err = recovd_setup(recovd);
- if (err)
- GOTO(err_free, err);
-
- recovd->recovd_service = ptlrpc_init_svc(16* 1024,
- CONNMGR_REQUEST_PORTAL,
- CONNMGR_REPLY_PORTAL,
- "self", connmgr_handle);
- if (!recovd->recovd_service) {
- CERROR("failed to start service\n");
- GOTO(err_recovd, err = -ENOMEM);
- }
-
- ptlrpc_init_client(NULL, NULL, CONNMGR_REQUEST_PORTAL,
- CONNMGR_REPLY_PORTAL, recovd->recovd_client);
- recovd->recovd_client->cli_name = "connmgr";
-
- err = ptlrpc_start_thread(obddev, recovd->recovd_service,
- "lustre_connmgr");
- if (err) {
- CERROR("cannot start thread\n");
- GOTO(err_svc, err);
- }
-
- ptlrpc_connmgr = recovd;
- RETURN(0);
-
-err_svc:
- ptlrpc_unregister_service(recovd->recovd_service);
-err_recovd:
- recovd_cleanup(recovd);
-err_free:
- OBD_FREE(recovd->recovd_client, sizeof(*recovd->recovd_client));
-err_dec:
- MOD_DEC_USE_COUNT;
- RETURN(err);
-}
-
-int connmgr_cleanup(struct obd_device *dev)
-{
- struct recovd_obd *recovd = &dev->u.recovd;
- int err;
-
- err = recovd_cleanup(recovd);
- if (err)
- LBUG();
-
- ptlrpc_stop_all_threads(recovd->recovd_service);
- ptlrpc_unregister_service(recovd->recovd_service);
- ptlrpc_cleanup_client(recovd->recovd_client);
- OBD_FREE(recovd->recovd_client, sizeof(*recovd->recovd_client));
- MOD_DEC_USE_COUNT;
- RETURN(0);
-}
-
-
-int connmgr_iocontrol(long cmd, struct lustre_handle *conn, int len, void *karg,
- void *uarg)
-{
- struct obd_device *obd = class_conn2obd(conn);
- struct recovd_obd *recovd = &obd->u.recovd;
-
- ENTRY;
- if (cmd == OBD_IOC_RECOVD_NEWCONN) {
- spin_lock(&recovd->recovd_lock);
- recovd->recovd_flags |= RECOVD_UPCALL_ANSWER;
- recovd->recovd_wakeup_flag = 1;
- wake_up(&recovd->recovd_waitq);
- spin_unlock(&recovd->recovd_lock);
- EXIT;
- }
- return 0;
-}
-
-
-/* use obd ops to offer management infrastructure */
-static struct obd_ops recovd_obd_ops = {
- o_setup: connmgr_setup,
- o_cleanup: connmgr_cleanup,
- o_iocontrol: connmgr_iocontrol,
-};
-
-static int __init ptlrpc_init(void)
-{
- int rc;
- rc = ptlrpc_init_portals();
- if (rc)
- RETURN(rc);
- ptlrpc_init_connection();
- class_register_type(&recovd_obd_ops, LUSTRE_HA_NAME);
- return 0;
-}
-
-static void __exit ptlrpc_exit(void)
-{
- class_unregister_type(LUSTRE_HA_NAME);
- ptlrpc_exit_portals();
- ptlrpc_cleanup_connection();
-}
-
-/* events.c */
-EXPORT_SYMBOL(ptlrpc_check_bulk_sent);
-EXPORT_SYMBOL(ptlrpc_check_bulk_received);
-
-/* connmgr.c */
-EXPORT_SYMBOL(ptlrpc_connmgr);
-EXPORT_SYMBOL(connmgr_connect);
-EXPORT_SYMBOL(connmgr_handle);
-EXPORT_SYMBOL(recovd_cli_fail);
-EXPORT_SYMBOL(recovd_cli_manage);
-EXPORT_SYMBOL(recovd_cli_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);
-
-/* 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_prep_req2);
-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(ptlrpc_check_status);
-
-/* 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);
-
-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);
-extern int ptl_handled_rpc(struct ptlrpc_service *service, void *start);
-
-static int ptlrpc_check_event(struct ptlrpc_service *svc,
- struct ptlrpc_thread *thread, ptl_event_t *event)
-{
- int rc = 0;
- ENTRY;
-
- spin_lock(&svc->srv_lock);
- if (thread->t_flags & SVC_STOPPING)
- GOTO(out, rc = 1);
-
- if (ptl_is_valid_handle(&svc->srv_eq_h)) {
- int err;
- err = PtlEQGet(svc->srv_eq_h, event);
-
- if (err == PTL_OK) {
- thread->t_flags |= SVC_EVENT;
- GOTO(out, rc = 1);
- }
-
- if (err != PTL_EQ_EMPTY) {
- CERROR("BUG: PtlEQGet returned %d\n", rc);
- LBUG();
- }
-
- GOTO(out, rc = 0);
- }
-
- EXIT;
- out:
- spin_unlock(&svc->srv_lock);
- return rc;
-}
-
-struct ptlrpc_service *
-ptlrpc_init_svc(__u32 bufsize, int req_portal, int rep_portal, char *uuid,
- svc_handler_t handler)
-{
- int err;
- int rc, i;
- struct ptlrpc_service *service;
- ENTRY;
-
- OBD_ALLOC(service, sizeof(*service));
- if (!service) {
- LBUG();
- RETURN(NULL);
- }
-
- spin_lock_init(&service->srv_lock);
- INIT_LIST_HEAD(&service->srv_reqs);
- INIT_LIST_HEAD(&service->srv_threads);
- init_waitqueue_head(&service->srv_waitq);
-
- service->srv_buf_size = bufsize;
- 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("cannot get peer for uuid '%s'\n", uuid);
- OBD_FREE(service, sizeof(*service));
- RETURN(NULL);
- }
-
- service->srv_ring_length = RPC_RING_LENGTH;
-
- rc = PtlEQAlloc(service->srv_self.peer_ni, 1024, request_in_callback,
- &(service->srv_eq_h));
-
- if (rc != PTL_OK) {
- CERROR("PtlEQAlloc failed: %d\n", rc);
- LBUG();
- OBD_FREE(service, sizeof(*service));
- RETURN(NULL);
- }
-
- for (i = 0; i < service->srv_ring_length; i++) {
- OBD_ALLOC(service->srv_buf[i], service->srv_buf_size);
- if (service->srv_buf[i] == NULL) {
- CERROR("no memory\n");
- LBUG();
- GOTO(err_ring, NULL);
- }
- service->srv_ref_count[i] = 0;
- ptlrpc_link_svc_me(service, i);
- }
-
- CDEBUG(D_NET, "Starting service listening on portal %d\n",
- service->srv_req_portal);
-
- RETURN(service);
-err_ring:
- service->srv_ring_length = i;
- 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 lustre_peer peer;
- void *start;
- int rc;
-
- /* FIXME: If we move to an event-driven model, we should put the request
- * on the stack of mds_handle instead. */
- LASSERT ((event->mem_desc.options & PTL_MD_IOV) == 0);
- start = event->mem_desc.start;
-
- 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->mem_desc.length;
-
- if (request.rq_reqlen < sizeof(struct lustre_msg)) {
- CERROR("incomplete request (%d): ptl %d from %Lx xid %Ld\n",
- request.rq_reqlen, svc->srv_req_portal,
- event->initiator.nid, request.rq_xid);
- spin_unlock(&svc->srv_lock);
- return -EINVAL;
- }
-
- if (request.rq_reqmsg->magic != PTLRPC_MSG_MAGIC) {
- CERROR("wrong lustre_msg magic %d: ptl %d from %Lx xid %Ld\n",
- request.rq_reqmsg->magic, svc->srv_req_portal,
- event->initiator.nid, request.rq_xid);
- spin_unlock(&svc->srv_lock);
- return -EINVAL;
- }
-
- if (request.rq_reqmsg->version != PTLRPC_MSG_VERSION) {
- CERROR("wrong lustre_msg version %d: ptl %d from %Lx xid %Ld\n",
- request.rq_reqmsg->version, svc->srv_req_portal,
- event->initiator.nid, request.rq_xid);
- spin_unlock(&svc->srv_lock);
- return -EINVAL;
- }
-
- CDEBUG(D_NET, "got req %Ld\n", request.rq_xid);
-
- peer.peer_nid = event->initiator.nid;
- /* FIXME: this NI should be the incoming NI.
- * We don't know how to find that from here. */
- 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 {
- request.rq_connection = ptlrpc_get_connection(&peer);
- }
-
- spin_unlock(&svc->srv_lock);
- rc = svc->srv_handler(&request);
- ptlrpc_put_connection(request.rq_connection);
- ptl_handled_rpc(svc, start);
- return rc;
-}
-
-void ptlrpc_rotate_reqbufs(struct ptlrpc_service *service,
- ptl_event_t *ev)
-{
- int index;
-
- LASSERT ((ev->mem_desc.options & PTL_MD_IOV) == 0);
-
- for (index = 0; index < service->srv_ring_length; index++)
- if (service->srv_buf[index] == ev->mem_desc.start)
- break;
-
- if (index == service->srv_ring_length)
- LBUG();
-
- service->srv_ref_count[index]++;
-
- if (ptl_is_valid_handle(&ev->unlinked_me)) {
- int idx;
-
- for (idx = 0; idx < service->srv_ring_length; idx++)
- if (service->srv_me_h[idx].handle_idx ==
- ev->unlinked_me.handle_idx)
- break;
- if (idx == service->srv_ring_length)
- LBUG();
-
- CDEBUG(D_NET, "unlinked %d\n", idx);
- ptl_set_inv_handle(&(service->srv_me_h[idx]));
-
- if (service->srv_ref_count[idx] == 0)
- ptlrpc_link_svc_me(service, idx);
- }
-}
-
-static int ptlrpc_main(void *arg)
-{
- int rc;
- 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;
-
- ENTRY;
-
- lock_kernel();
- daemonize();
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
-
- sprintf(current->comm, data->name);
-
- /* 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) {
- ptl_event_t event;
-
- wait_event(svc->srv_waitq,
- ptlrpc_check_event(svc, thread, &event));
-
- spin_lock(&svc->srv_lock);
-
- if (thread->t_flags & SVC_STOPPING) {
- thread->t_flags &= ~SVC_STOPPING;
- spin_unlock(&svc->srv_lock);
- EXIT;
- break;
- }
-
- if (thread->t_flags & SVC_EVENT) {
- thread->t_flags &= ~SVC_EVENT;
- ptlrpc_rotate_reqbufs(svc, &event);
-
- rc = handle_incoming_request(obddev, svc, &event);
- thread->t_flags &= ~SVC_EVENT;
- continue;
- }
-
- CERROR("unknown break in service");
- spin_unlock(&svc->srv_lock);
- EXIT;
- break;
- }
-
- thread->t_flags = SVC_STOPPED;
- wake_up(&thread->t_ctl_waitq);
- CDEBUG(D_NET, "service thread exiting, process %d\n", current->pid);
- return 0;
-}
-
-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_FS | CLONE_FILES);
- if (rc < 0) {
- CERROR("cannot start thread\n");
- RETURN(-EINVAL);
- }
- wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_RUNNING);
-
- RETURN(0);
-}
-
-int ptlrpc_unregister_service(struct ptlrpc_service *service)
-{
- int rc, i;
-
- for (i = 0; i < service->srv_ring_length; i++) {
- if (ptl_is_valid_handle(&(service->srv_me_h[i]))) {
- rc = PtlMEUnlink(service->srv_me_h[i]);
- if (rc)
- CERROR("PtlMEUnlink failed: %d\n", rc);
- ptl_set_inv_handle(&(service->srv_me_h[i]));
- }
-
- if (service->srv_buf[i] != NULL)
- OBD_FREE(service->srv_buf[i], service->srv_buf_size);
- service->srv_buf[i] = NULL;
- }
-
- rc = PtlEQFree(service->srv_eq_h);
- if (rc)
- CERROR("PtlEQFree failed: %d\n", rc);
-
- if (!list_empty(&service->srv_reqs)) {
- // XXX reply with errors and clean up
- CERROR("Request list not empty!\n");
- }
-
- OBD_FREE(service, sizeof(*service));
- return 0;
-}
+++ /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 mkobddevs obdtrace_demo.scr lustre.spec $(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/bash
-#
-# 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: obdctl
-# config: /etc/lustre/lustre.cfg
-# pidfile: /var/run/lustre.pid
-
-SERVICE=lustre
-LOCK=/var/lock/subsys/$SERVICE
-
-# 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
-
-[ -f /usr/sbin/obdctl ] || exit 0
-
-start() {
- echo -n $"Starting $SERVICE: "
- /usr/sbin/llrsetup.sh
- RETVAL=$?
- echo $SERVICE
- [ $RETVAL = 0 ] && touch $LOCK
-}
-
-stop() {
- echo -n $"Shutting down $SERVICE: "
- /usr/sbin/llcleanup.sh
- 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@
-Release: 0208101108
-
-Summary: Lustre Lite File System
-Name: lustre-lite
-Version: %{version}
-Copyright: GPL
-Group: Utilities/System
-Requires: lustre-modules, libxml2
-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-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
-
-%package -n lustre-source
-Summary: Object-Based Disk storage driver source
-Group: Development/Kernel
-
-%description -n lustre-source
-Lustre Lite Source for further development
-
-%prep
-%setup -qn lustre-%{version}
-
-%build
-rm -rf $RPM_BUILD_ROOT
-
-# Set an explicit path to our Linux tree, if we can.
-./configure --enable-linuxdir='%{linuxdir}' --enable-portalsdir='%{portalsdir}'
-make
-
-%install
-make install prefix=$RPM_BUILD_ROOT
-
-# Create the pristine source directory.
-make distclean
-mkdir -p $RPM_BUILD_ROOT/usr/src/lustre-%{version}
-find . -print | cpio -ap $RPM_BUILD_ROOT/usr/src/lustre-%{version}
-
-
-%files
-#%attr(-, root, root) /usr/sbin/obdctl
-%attr(-, root, root) /usr/sbin/lctl
-%attr(-, root, root) /usr/sbin/llsetup.sh
-%attr(-, root, root) /usr/sbin/llrsetup.sh
-%attr(-, root, root) /usr/sbin/llcleanup.sh
-%attr(-, root, root) /lib/lustre/common.sh
-%attr(-, root, root) /etc/lustre/lustre.cfg
-%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/obdfs.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
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-set -vx
-rm -f TAGS ; find . -name '*.h' -or -name '*.c' | xargs etags
-rm -f ctags; find . -name '*.h' -or -name '*.c' | xargs ctags
+++ /dev/null
-#!/bin/sh -x
-# Copyright (C) 2001 Cluster File Systems, Inc.
-#
-# This code is issued under the GNU General Public License.
-# See the file COPYING in this distribution
-
-mknod -m 0600 /dev/obd0 c 186 0
-mknod -m 0600 /dev/obd1 c 186 1
-mknod -m 0600 /dev/obd2 c 186 2
-mknod -m 0600 /dev/obd3 c 186 3
-mknod -m 0600 /dev/obd4 c 186 4
-mknod -m 0600 /dev/obd5 c 186 5
-mknod -m 0600 /dev/obd6 c 186 6
-mknod -m 0600 /dev/obd7 c 186 7
+++ /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
-# Print OS version
-shell uname -r
-# Insert Lustre kernel modules
-insmod class/obdclass.o
-procsys trace 0
-procsys debug 0
-insmod ext2obd/obdext2.o
-insmod obdtrace/obdtrace.o
-insmod obdfs/obdfs.o
-# Configure direct driver on /dev/obd0
-device /dev/obd0
-attach obdext2
-setup /dev/sda2
-# Configure obdtrace on /dev/obd1
-device /dev/obd1
-attach obdtrace
-setup /dev/obd0
-# What's the obd status
-status
-shell cat /proc/lustre/obd/1/stats
-# mount obd file system
-shell mkdir -p /mnt/obd
-shell mount -t obdfs -odevice=/dev/obd1 none /mnt/obd
-shell mount
-# Prepare a data set (tar file of current directory)
-shell rm -f /tmp/obdtrace_test.tar
-shell tar cf /tmp/obdtrace_test.tar .
-# make a directory on obd device
-shell mkdir -p /mnt/obd/obdtrace_test_dir
-# Unpack tarfile to obd device
-shell tar -C /mnt/obd/obdtrace_test_dir -xf /tmp/obdtrace_test.tar
-shell rm -rf /mnt/obd/obdtrace_test_dir
-# Check obdtrace performance stats
-status
-shell cat /proc/lustre/obd/1/stats
-shell echo 0 > /proc/lustre/obd/1/stats
-shell cat /proc/lustre/obd/1/stats
-# Umount file system
-shell umount /mnt/obd
-# Cleanup /tmp
-shell rm -f /tmp/obdtrace_test.tar
-# Dismantle /dev/obd1
-device /dev/obd1
-cleanup
-detach
-close
-# Dismantle /dev/obd0
-device /dev/obd0
-cleanup
-detach
-close
-# Remove all loaded kernel modules
-rmmod obdfs
-rmmod obdtrace
-rmmod obdext2
-rmmod obdclass
+++ /dev/null
-.Xrefs
-config.log
-config.status
-configure
-Makefile
-Makefile.in
-.deps
-TAGS
-openunlink
-testreq
-truncate
-directio
-openme
-writeme
-mcreate
-munlink
-tchmod
-toexcl
-fsx
+++ /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
-pkglibdir = @libdir@/$(PACKAGE)
-pkgcfgdir = @sysconfdir@/$(PACKAGE)
-EXTRA_DIST = $(sbin_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 \
- elan-client.cfg mds.cfg
-sbin_SCRIPTS = llsetup.sh llrsetup.sh llcleanup.sh
-noinst_DATA = ext2_10000.gz ext2_25000.gz ext3_10000.gz lov.xml
-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
-pkglib_SCRIPTS = common.sh
-pkgcfg_DATA = lustre.cfg
-noinst_PROGRAMS = openunlink testreq truncate directio openme writeme mcreate
-noinst_PROGRAMS += munlink tchmod toexcl fsx #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
-
-include $(top_srcdir)/Rules
+++ /dev/null
-A variety of tests can be run or environments set up.
-
-1. runregression-net
-
-Usage on server:
- llsetup.sh marcus-echo-server.cfg
-
-with marcus-echo-server.cfg:
-
- NETWORK=elan
- LOCALHOST=4
- SERVER=4
- SETUP_OST=y
- OSTTYPE=obdecho
-
-
-Usage on client:
-runregression-net marcus-echo-client.cfg
-
-with marcus-echo-client.cfg:
-
- NETWORK=elan
- LOCALHOST=5
- SERVER=4
- SETUP_OSC=y
-
-If things are alright it goes through all the tests single threaded,
-multithreaded, getattr and brw (both read and write).
-
-2. How to build .cfg scripts:
-The various .cfg scripts in the tests/ directory can be used as building
-blocks for full configurations. For example, the above configurations are:
-
- cat elan-server.cfg obdecho.cfg > marcus-echo-server.cfg
- cat elan-client.cfg client-echo.cfg > marcus-echo-client.cfg
-
-You _could_ specify multiple .cfg files as the parameters to llsetup if
-you are doing something uncommon, but it is probably just easer to build
-a whole config file in one shot, edit it as needed, and use that file instead.
-
-For a loopback setup with a mounted filesystem, you could do something like:
-
- cat net-local.cfg mds.cfg obdext2.cfg client-mount.cfg > uml.cfg
-
-The order of the specified .cfg files does not matter.
-
-Since the .cfg script is a shell script, you can add conditional setup in
-case you want to avoid changing your configuration if you need to run on
-a different host. You could, for example, have marcus-echo-server.cfg:
-
- NETWORK=elan
- HOST=`hostname | sed "s/\..*//"`
- case $HOST in
- dev*) LOCALHOST=`echo $HOST | sed "s/dev//"`
- SERVER=$LOCALHOST
- NETWORK=elan ;;
- *) LOCALHOST=$HOST
- SERVER=$LOCALHOST
- NETWORK=tcp ;;
- esac
- SETUP_OST=y
- OSTTYPE=obdecho
-
-You would, of course, need a marcus-echo-client.cfg to match.
-
-3. runtests
-
-The runtests script does a series of simple file-based tests using
-a filesystem. You need to use a configuration which includes a real
-OST and MDS setup, and an OSC mount. For example, a configuration
-marcus-obd-server.cfg:
-
- SETUP_MDS=y
- NETWORK=elan
- LOCALHOST=4
- SERVER=4
- MDSFS=ext3
- MDSDEV=/tmp/mds
- MDSSIZE=10000
- OSTDEV=/tmp/ost
- OSTSIZE=10000
- OSTFS=ext2
- OSTTYPE=obdext2
- SETUP_OST=y
- SETUP_LDLM=y
-
-As with the echo test, you run "sh llsetup.sh marcus-obd-server.cfg" on
-the server to configure it.
-
-For marcus-obd-client.cfg you only need to include the client data:
-
- NETWORK=elan
- LOCALHOST=5
- SERVER=4
- SETUP_OSC=y
- OSCMT=/mnt/lustre
- SETUP_MOUNT=y
- SETUP_LDLM=y
-
-You run the test via "sh runtests marcus-obd-client.cfg".
+++ /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 $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
-
- [ -z "$MDS_RSH" ] && MDS_RSH="eval"
- [ -z "$OST_RSH" ] && OST_RSH="eval"
- [ -z "$OSC_RSH" ] && OSC_RSH="eval"
-}
-
-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" -o -z "$MDSNODE" -o -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=
- ;;
- tcp) do_insmod $PORTALS/linux/socknal/ksocknal.o || exit -1
- MYNID="mynid $LOCALHOST"
- ;;
- *) fail "$0: unknown NETWORK '$NETWORK'" ;;
- esac
-
- start_acceptor
-
- $PTLCTL <<- EOF
- network $NETWORK
- $MYNID
- connect $MDSNODE $PORT
- add_uuid $MDSNODE $MDSNODE
- connect $OSTNODE $PORT
- add_uuid $OSTNODE $OSTNODE
- connect $DLM $PORT
- add_uuid $DLM $DLM
- add_uuid self $LOCALHOST
- quit
-EOF
-}
-
-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
- 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
- lovconfig ${LOVUUID} 1 4096 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
-
- $OBDCTL <<- EOF || return $rc
- newdev
- attach osc $THEOSC ${THEOSC}-`hostname`
- setup OBDUUID $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
- [ "$MDC_NAMES" ] || MDC_NAMES=MDCDEV
- [ "$OSC_NAMES" ] || OSC_NAMES=OSCDEV
- [ -z "$MOUNT_LIST" -a "$OSCMT" ] && MOUNT_LIST="MT" && MT="$OSCMT OSCDEV MDCDEV"
-
- [ "$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() {
- [ "$MDS_RSH" ] && echo "Turn OFF debug on MDS" && $MDS_RSH "$DEBUG_OFF"
- [ "$OST_RSH" ] && echo "Turn OFF debug on OST" && $OST_RSH "$DEBUG_OFF"
-}
-
-debug_server_on() {
- [ "$MDS_RSH" ] && echo "Turn ON debug on MDS" && $MDS_RSH "$DEBUG_ON"
- [ "$OST_RSH" ] && echo "Turn ON debug on OST" && $OST_RSH "$DEBUG_ON"
-}
-
-debug_client_off() {
- echo "Turning OFF debug on client" && $OSC_RSH "$DEBUG_OFF"
-}
-
-debug_client_on() {
- echo "Turning ON debug on client" && $OSC_RSH "$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.3.$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
- [ "$MDC_NAMES" ] || MDC_NAMES=MDCDEV
- [ "$OSC_NAMES" ] || OSC_NAMES=OSCDEV
- [ -z "$MOUNT_LIST" -a "$OSCMT" ] && MOUNT_LIST="MT" && MT="$OSCMT OSCDEV MDCDEV"
-
- [ "$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
-
-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) {
- $tmp =~ /.*error: (.*)\n/;
- print "Created $path: $1\n";
- } else {
- print "Created $path: Success\n";
- }
- } else {
- open(FH, ">$path") || die "open($PATH): $!";
- print "Opened $path: Success\n";
- 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";
- if (unlink($path)) {
- print "Unlinked $path: Success\n";
- } else {
- print "Unlinked $path: $!\n";
- }
-}
-print "Done.\n";
+++ /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>
-#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;
- 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 */
-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 log_entry *le;
-
- le = &oplog[logptr];
- 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;
- prt("%d(%d mod 256): ", opnum, opnum%256);
- lp = &oplog[i];
- 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.fsxgood\")\n",
- fname, fname);
- }
- 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)
-{
- off_t ret;
- unsigned iret;
-
- offset -= offset % readbdy;
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size read\n");
- log4(OP_SKIPPED, OP_READ, offset, size);
- 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);
- return;
- }
-
- log4(OP_READ, offset, size, 0);
-
- if (testcalls <= simulatedopcount)
- return;
-
- if (!quiet && ((progressinterval &&
- testcalls % progressinterval == 0) ||
- (debug &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))))
- prt("%lu read\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls,
- 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)
-{
- unsigned pg_offset;
- unsigned map_size;
- char *p;
-
- offset -= offset % readbdy;
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size read\n");
- log4(OP_SKIPPED, OP_MAPREAD, offset, size);
- 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);
- return;
- }
-
- log4(OP_MAPREAD, offset, size, 0);
-
- if (testcalls <= simulatedopcount)
- return;
-
- if (!quiet && ((progressinterval &&
- testcalls % progressinterval == 0) ||
- (debug &&
- (monitorstart == -1 ||
- (offset + size > monitorstart &&
- (monitorend == -1 || offset <= monitorend))))))
- prt("%lu mapread\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls,
- 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)
-{
- off_t ret;
- unsigned iret;
-
- offset -= offset % writebdy;
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size write\n");
- log4(OP_SKIPPED, OP_WRITE, offset, size);
- return;
- }
-
- log4(OP_WRITE, offset, size, file_size);
-
- 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 write\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls,
- 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)
-{
- unsigned pg_offset;
- unsigned map_size;
- off_t cur_filesize;
- char *p;
-
- offset -= offset % writebdy;
- if (size == 0) {
- if (!quiet && testcalls > simulatedopcount)
- prt("skipping zero size write\n");
- log4(OP_SKIPPED, OP_MAPWRITE, offset, size);
- return;
- }
- cur_filesize = file_size;
-
- log4(OP_MAPWRITE, offset, size, 0);
-
- 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 mapwrite\t0x%x thru\t0x%x\t(0x%x bytes)\n", testcalls,
- 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)
-{
- int oldsize = file_size;
-
- size -= size % truncbdy;
- 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);
-
- 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 trunc\tfrom 0x%x to 0x%x\n", testcalls, 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)
-{
- if (testcalls <= simulatedopcount)
- return;
-
- if (debug)
- prt("%lu close/open\n", testcalls);
- 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);
-}
-
-
-int
-main(int argc, char **argv)
-{
- int i, style, ch;
- char *endp;
- char goodfile[1024];
- char logfile[1024];
-
- 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, "/");
- 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, fname, 256);
- strcat (goodfile, ".fsxgood");
- fsxgoodfd = open(goodfile, O_RDWR|O_CREAT|O_TRUNC, 0666);
- if (fsxgoodfd < 0) {
- prterr(goodfile);
- exit(92);
- }
- strncat(logfile, 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
-
-my ($line, $memory);
-my $debug_line = 0;
-
-while ($line = <>) {
- $debug_line++;
- my ($file, $func, $lno, $name, $size, $addr, $type);
- if ($line =~ m/^.*\(@\d+ (.*):(.*)\,l\. (\d+) .* k(.*) '(.*)': (\d+) at (.*) \(tot .*$/) {
- $file = $1;
- $func = $2;
- $lno = $3;
- $type = $4;
- $name = $5;
- $size = $6;
- $addr = $7;
- 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 "*** 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 "*** Free different size ($memory->{$addr}->{size} alloced, $size freed).\n";
- print " malloc at $memory->{$addr}->{file}:$memory->{$addr}->{func}:$memory->{$addr}->{lno}, free at $file:$func:$lno\n";
- next;
- }
-
- delete $memory->{$addr};
- }
-}
-
-my $key;
-foreach $key (keys(%{$memory})) {
- my ($oldname, $oldsize, $oldfile, $oldfunc, $oldlno) = $memory->{$key};
- print "*** 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]
-
-And to stop it:
-ldlm_regress_stop
-**********************************************
-EOF
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-export DEBUG_WAIT=yes
-. $SRCDIR/llsetup.sh $SRCDIR/net-local.cfg $SRCDIR/obdecho.cfg $SRCDIR/client-echo.cfg
-
-cat <<EOF
-
-run getattr tests as:
-$OBDCTL --device `$OBDCTL name2dev OSCDEV` test_getattr 1000000
-EOF
+++ /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
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-export DEBUG_WAIT=yes
-. $SRCDIR/llsetup.sh $SRCDIR/net-local.cfg $SRCDIR/mds.cfg $SRCDIR/obdfilter.cfg $SRCDIR/client-mount.cfg $SRCDIR/ldlm.cfg || exit 2
-
-debug_client_on
-#debug_client_off
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-. $SRCDIR/llcleanup.sh $SRCDIR/net-local.cfg $SRCDIR/mds.cfg $SRCDIR/obdfilter.cfg $SRCDIR/client-mount.cfg $SRCDIR/ldlm.cfg || exit 2
\ No newline at end of file
+++ /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
-
-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/obdfilter.cfg $SRCDIR/ldlm.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 "$@"
-
-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
-<?xml version="1.0"?>
-<!DOCTYPE lustre SYSTEM "../utils/lustre.dtd">
-
-<lustre>
- <node name="localhost" uuid="localhost-UUID">
- <network type='tcp' name='net' uuid="net-UUID" >
- <server>localhost</server>
- <port>2432</port>
- </network>
- <profile_ref uuidref="local-profile-UUID"/>
- </node>
-
- <profile name="local-profile" uuid="local-profile-UUID">
- <service_ref uuidref="net-UUID"/>
- <service_ref uuidref="ldlm-srv-UUID"/>
- <service_ref uuidref="lov1-UUID"/>
- <service_ref uuidref="mtpt1-UUID"/>
- <service_ref uuidref="mdc1-UUID"/>
- <service_ref uuidref="mds-UUID"/>
- <service_ref uuidref="obd1-UUID"/>
- <service_ref uuidref="obd2-UUID"/>
- <service_ref uuidref="ost1-UUID"/>
- <service_ref uuidref="ost2-UUID"/>
- <service_ref uuidref="osc1-UUID"/>
- <service_ref uuidref="osc2-UUID"/>
- </profile>
-
- <ldlm name="ldlm-srv" uuid="ldlm-srv-UUID"/>
-
- <lov name="lov1" uuid="lov1-UUID">
- <mdc_ref uuidref="mdc1-UUID"/>
- <devices stripesize="65536" stripeoffset="0" pattern="0">
- <osc_ref uuidref="osc1-UUID"/>
- <osc_ref uuidref="osc2-UUID"/>
- </devices>
- </lov>
-
- <mdc name="mdc1" uuid="mdc1-UUID">
- <network_ref name='net' uuidref='net-UUID'/>
- <mds_ref uuidref="mds-UUID"/>
- </mdc>
-
- <mds name="mds" uuid="mds-UUID">
- <network_ref name='net-local' uuidref="net-local-UUID"/>
- <fstype>extN</fstype>
- <device size="50000">/tmp/mds</device>
- <autoformat>yes</autoformat>
- </mds>
-
- <osc name="osc1" uuid="osc1-UUID">
- <network_ref name='net' uuidref='net-UUID'/>
- <obd_ref uuidref="obd1-UUID"/>
- </osc>
-
- <osc name="osc2" uuid="osc2-UUID">
- <network_ref name='net' uuidref='net-UUID'/>
- <obd_ref uuidref="obd2-UUID"/>
- </osc>
-
- <ost name="ost1" uuid="ost1-UUID">
- <network_ref name='net' uuidref='net-UUID'/>
- <obd_ref uuidref='obd1-UUID'/>
- </ost>
-
- <ost name="ost2" uuid="ost2-UUID">
- <network_ref name='net' uuidref='net-UUID'/>
- <obd_ref uuidref='obd2-UUID'/>
- </ost>
-
- <obd name="obd1" uuid="obd1-UUID" type="obdfilter">
- <fstype>extN</fstype>
- <device size="100000">/tmp/obd1</device>
- <autoformat>yes</autoformat>
- </obd>
-
- <obd name="obd2" uuid="obd2-UUID" type="obdfilter">
- <fstype>extN</fstype>
- <device size="100000">/tmp/obd2</device>
- <autoformat>yes</autoformat>
- </obd>
-
- <mountpoint name="mtpt1" uuid="mtpt1-UUID">
- <path>/mnt/lustre</path>
- <mdc_ref uuidref="mdc1-UUID"/>
- <osc_ref uuidref="lov1-UUID"/>
- </mountpoint>
-
-</lustre>
+++ /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=2432
-
-# 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
-#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 = mknod(argv[1], S_IFREG| 0444, 0);
- if (rc) {
- printf("mknod(%s) error: %s\n", argv[1], strerror(errno));
- }
- return rc;
-}
+++ /dev/null
-#!/bin/sh
-
-SRCDIR="`dirname $0`"
-. $SRCDIR/common.sh
-
-NETWORK=tcp
-LOCALHOST=localhost
-SERVER=localhost
-PORT=2432
-
-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
-<?xml version="1.0"?>
-<!DOCTYPE lustre SYSTEM "../utils/lustre.dtd">
-
-<lustre>
- <node name="uml1" uuid="uml1-UUID">
- <network type='tcp' name='uml1' uuid="uml1-net-UUID" >
- <server>uml1</server>
- <port>666</port>
- </network>
- <profile_ref uuidref="uml1-prof-UUID"/>
- </node>
-
- <profile name="uml1-prof" uuid="uml1-prof-UUID">
- <service_ref uuidref="uml1-net-UUID"/>
- <service_ref uuidref="ldlm-srv-UUID"/>
- <service_ref uuidref="mds1-UUID"/>
- </profile>
-
- <node name="uml2" uuid="uml2-UUID">
- <network type='tcp' name='uml2' uuid="uml2-net-UUID" >
- <server>uml2</server>
- <port>666</port>
- </network>
- <profile_ref uuidref="uml2-prof-UUID"/>
- </node>
-
- <profile name="uml2-prof" uuid="uml2-prof-UUID">
- <service_ref uuidref="uml2-net-UUID"/>
- <service_ref uuidref="ldlm-srv-UUID"/>
- <service_ref uuidref="mds2-UUID"/>
- <service_ref uuidref="mdc1-UUID"/>
- <service_ref uuidref="obd1-UUID"/>
- <service_ref uuidref="ost1-UUID"/>
- <service_ref uuidref="osc1-UUID"/>
- <service_ref uuidref="mtpt1-UUID"/>
- </profile>
-
-
- <ldlm name="ldlm-srv" uuid="ldlm-srv-UUID"/>
-
- <mdc name="mdc1" uuid="mdc1-UUID">
- <network_ref uuidref='uml1-net-UUID'/> <!-- is this extra net needed ?? -->
- <mds_ref uuidref="mds1-UUID"/>
- </mdc>
-
- <mds name="mds1" uuid="mds1-UUID">
- <network_ref uuidref="uml1-UUID"/>
- <fstype>extN</fstype>
- <device size="50000">/tmp/mds</device>
- <autoformat>yes</autoformat>
- <failover_ref uuidref="mds2-UUID"/>
- </mds>
-
- <mds name="mds2" uuid="mds2-UUID">
- <network_ref uuidref="uml2-UUID"/>
- <fstype>extN</fstype>
- <device size="50000">/tmp/mds</device>
- <autoformat>yes</autoformat>
- </mds>
-
- <osc name="osc1" uuid="osc1-UUID">
- <network_ref uuidref='uml2-net-UUID'/>
- <obd_ref uuidref="obd1-UUID"/>
- </osc>
-
- <ost name="ost1" uuid="ost1-UUID">
- <network_ref uuidref='uml2-net-UUID'/>
- <obd_ref uuidref='obd1-UUID'/>
- </ost>
-
- <obd name="obd1" uuid="obd1-UUID" type="obdfilter">
- <fstype>extN</fstype>
- <device size="100000">/tmp/obd1</device>
- <autoformat>yes</autoformat>
- </obd>
-
- <obd name="obd2" uuid="obd2-UUID" type="obdfilter">
- <fstype>extN</fstype>
- <device size="100000">/tmp/obd2</device>
- <autoformat>yes</autoformat>
- </obd>
-
- <mountpoint name="mtpt1" uuid="mtpt1-UUID">
- <path>/mnt/lustre</path>
- <mdc_ref uuidref="mdc1-UUID"/>
- <osc_ref uuidref="osc1-UUID"/>
- </mountpoint>
-
-</lustre>
-
+++ /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
-<?xml version="1.0"?>
-<!DOCTYPE lustre SYSTEM "lustre.dtd">
-
-<lustre>
- <node id="dev5" uuid="dev5-UUID">
- <profile_id num="1" id="mds-profile-1" uuid="mds-profile-1-UUID"></profile_id>
- </node>
-
- <profile id="mds-profile-1" uuid="mds-profile-1-UUID">
- <service_id num="1" id="osc-srv-1" uuid="osc-srv-1-UUID"></service_id>
- <service_id num="2" id="mds-srv-1" uuid="mds-srv-1-UUID"></service_id>
- </profile>
-
- <osc id="osc-srv-1" uuid="osc-srv-1-UUID">
- <network type="ip" address="192.168.0.1"></network>
- </osc>
-
- <mds id="mds-srv-1" uuid="mds-srv-1-UUID">
- <fstype>extN</fstype>
- <device>/dev/sda1</device>
- <server_id num="1" id="dev5" uuid="dev5-UUID"></server_id>
- <failover_id num="1" id="dev5" uuid="dev5-UUID"></failover_id>
- </mds>
-</lustre>
+++ /dev/null
-#!/bin/sh
-# Config file for running tests on a single host over loopback TCP
-NETWORK=tcp
+++ /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=2432
+++ /dev/null
-#!/bin/sh
-# Config file for running tests on a single host over loopback TCP
-NETWORK=tcp
-LOCALHOST=localhost
-SERVER=localhost
-PORT=2432
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE lustre SYSTEM "../utils/lustre.dtd">
-
-<lustre>
- <node name="local" uuid="local-UUID">
- <network type='tcp' name='net-local' uuid="net-local-UUID" >
- <server>localhost</server>
- <port>2432</port>
- </network>
- <profile_ref num="1" name="local-profile" uuidref="local-profile-UUID"/>
- </node>
-
- <profile name="local-profile" uuid="local-profile-UUID">
- <service_ref num="0" name="net-local" uuidref="net-local-UUID"/>
- <service_ref num="0" name="ldlm-srv" uuidref="ldlm-srv-UUID"/>
- <service_ref num="0" name="obd-srv" uuidref="obd-srv-UUID"/>
- <service_ref num="1" name="ost-srv" uuidref="ost-srv-UUID"/>
- <service_ref num="4" name="lustre-mnt" uuidref="lustre-mnt-UUID"/>
- <service_ref num="2" name="osc-srv" uuidref="osc-srv-UUID"/>
- <service_ref num="3" name="mdc-srv" uuidref="mdc-srv-UUID"/>
- <service_ref num="0" name="mds-srv" uuidref="mds-srv-UUID"/>
- </profile>
-
- <ldlm name="ldlm-srv" uuid="ldlm-srv-UUID"></ldlm>
-
- <obd name="obd-srv" uuid="obd-srv-UUID" type="obdfilter">
- <fstype>extN</fstype>
- <device size="100">/tmp/obd-srv</device>
- <autoformat>no</autoformat>
- </obd>
-
- <mds name="mds-srv" uuid="mds-srv-UUID">
- <network_ref name='net-local' uuidref="net-local-UUID"/>
- <fstype>extN</fstype>
- <device size="100">/tmp/mds-srv</device>
- <server_ref num="1" name="mds-srv" uuidref="mds-srv-UUID"/>
- <failover_ref num="1" name="mds-srv" uuidref="mds-srv-UUID"/>
- </mds>
-
- <ost name="ost-srv" uuid="ost-srv-UUID">
- <network_ref name='net-local' uuidref="net-local-UUID"/>
- <obd_ref num="1" name="$obd-srv" uuidref="obd-srv-UUID"/>
- <failover_ref num="1" name="$obd-srv" uuidref="obd-srv-UUID"/>
- </ost>
-
- <osc name="osc-srv" uuid="osc-srv-UUID">
- <network_ref name='net-local' uuidref="net-local-UUID"/>
- <obd_ref num="1" name="obd-srv" uuidref="obd-srv-UUID"/>
- </osc>
-
- <mdc name="mdc-srv" uuid="mdc-srv-UUID">
- <service_ref num="1" name="mds-srv" uuidref="mds-srv-UUID"/>
- </mdc>
-
- <mountpoint name="lustre-mnt" uuid="lustre-mnt-UUID">
- <path>/mnt/lustre</path>
- <fileset>dev</fileset>
- <mds_ref num="1" name="mds-srv" uuidref="mds-srv-UUID"/>
- </mountpoint>
-</lustre>
+++ /dev/null
-#!/bin/sh
-# Config file for setting up a remote server with a real OST
-NETWORK=tcp
-LOCALHOST=dev4
-SERVER=dev4
-PORT=2432
+++ /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
-#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 (before) %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 (before) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "closing\n");
- rc = close(fd);
- if (rc ) {
- fprintf(stderr, "close (before) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "opening again\n");
- fd = open(argv[1], O_RDWR );
- if (fd == -1) {
- fprintf(stderr, "open (before) %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "unlinking\n");
- rc = unlink(argv[1]);
- if (rc ) {
- fprintf(stderr, "open %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "reading\n");
- rc = read(fd, buf, strlen(T1) + 1);
- if (rc != strlen(T1) + 1) {
- fprintf(stderr, "read -after %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 -after unl %s\n", strerror(errno));
- exit(1);
- }
-
- fprintf(stderr, "seeking\n");
- rc = lseek(fd, 0, SEEK_SET);
- if (rc != 0 ) {
- fprintf(stderr, "seek (before write) %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 (before) %s (rc %d)\n", strerror(errno), rc);
- exit(1);
- }
-
- fprintf(stderr, "seeking\n");
- rc = lseek(fd, 0, SEEK_SET);
- if (rc != 0 ) {
- fprintf(stderr, "seek (before 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 trunc) %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 trunc\n");
- exit(1);
- }
-
- fprintf(stderr, "closing again\n");
- rc = close(fd);
- if (rc ) {
- fprintf(stderr, "close (before) %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=2432
-
-$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
-cd /mnt/lustre
-cp /usr/src/lustre/demos/dbench/client.txt .
-/usr/src/lustre/demos/dbench/dbench $1
+++ /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
-
-set -vx
-
-SRCDIR="`dirname $0`"
-. $SRCDIR/common.sh
-
-test_fail() {
- echo $1 > /proc/sys/lustre/fail_loc
- shift
- $* &
- sleep 1
- kill -9 $!
-
- echo 0 > /proc/sys/lustre/fail_loc
- umount /mnt/lustre || fail "cannot unmount /mnt/lustre"
- mount -t lustre_lite -o device=`$OBDCTL name2dev OSCDEV` none /mnt/lustre || fail "cannot remount device '`$OBDCTL name2dev OSCDEV`' on /mnt/lustre"
-}
-
-[ -c /dev/request ] || mknod /dev/request c 10 244
-
-[ "`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
-SIZE=5g
-COUNT=0
-[ $1 ] && SIZE=$1
-rm -f endiozone
-while date; do
- echo "Test #$COUNT"
- iozone -i 0 -i 1 -f /mnt/lustre/test.$$ -s $SIZE 2>&1 || exit $?
- COUNT=`expr $COUNT + 1`
- [ -f endiozone ] && rm endiozone && exit 0
-done | tee /tmp/iozone.log
+++ /dev/null
-#!/bin/sh
-export PATH=/sbin:/usr/sbin:$PATH
-
-SRCDIR="`dirname $0`/"
-. $SRCDIR/common.sh
-
-setup_opts $@
-
-setup_portals
-setup_lustre
-
-# 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_read test_brw_write; do
- case $CMD in
- test_brw_read) CMD=test_brw; RW=r ;;
- test_brw_write) CMD=test_brw; RW=w ;;
- *) RW= ;;
- esac
-
- setup_server || exit -1
- setup_client || exit -1
-
- OSC_DEVNO=`$OBDCTL name2dev OSCDEV`
-
- # We use '--threads 1 X' instead of '--device X' so that
- # obdctl can modnitor the forked thread for progress (TODO).
- $OBDCTL --threads 1 v $OSC_DEVNO $CMD 1 $RW v || exit -1
- $OBDCTL --threads 1 v $OSC_DEVNO $CMD 100 $RW v || exit -1
-
- #cleanup_client || exit -1
- #cleanup_server || exit -1
-
- #setup_server || exit -1
- #setup_client || exit -1
-
- debug_server_off
- debug_client_off
- $OBDCTL --threads 1 v $OSC_DEVNO $CMD 10000 $RW 100 || exit -1
- $OBDCTL --threads 1 v $OSC_DEVNO $CMD 1000000 $RW -10 || exit -1
-
- debug_server_on
- debug_client_on
- $OBDCTL --threads 2 v $OSC_DEVNO $CMD 100 $RW v || exit -1
-
- debug_server_off
- debug_client_off
- $OBDCTL --threads 2 v $OSC_DEVNO $CMD 10000 $RW 100 || exit -1
- $OBDCTL --threads 2 v $OSC_DEVNO $CMD 1000000 $RW -30 || exit -1
-
- $OBDCTL --threads 10 v $OSC_DEVNO $CMD 10000 $RW 1000 || exit -1
- $OBDCTL --threads 100 v $OSC_DEVNO $CMD 10000 $RW -30 || exit -1
-
- cleanup_client || exit -1
- cleanup_server || exit -1
-done
-
-cleanup_lustre
-cleanup_portals
+++ /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`"
-
-export PATH=/sbin:/usr/sbin:$SRCDIR:$PATH
-
-. $SRCDIR/common.sh
-
-ERROR=
-SRC=/etc
-[ "$COUNT" ] || COUNT=1000
-
-setup_opts $@
-
-[ "`mount | grep $OSCMT`" ] || echo | sh llsetup.sh $@ || exit 1
-
-# let's start slowly here...
-echo "touching $OSCMT"
-touch $OSCMT || fail "can't touch $OSCMT" 2
-echo "copying /etc/hosts to $OSCMT/hosts"
-cp /etc/hosts $OSCMT || fail "can't cp /etc/hosts to $OSCMT/hosts" 3
-echo "comparing /etc/hosts and $OSCMT/hosts"
-diff -u /etc/hosts $OSCMT/hosts || fail "$OSCMT/hosts different" 4
-
-# ok, that hopefully worked, so let's do a little more
-FILES=`find $SRC -type f | head -$COUNT`
-echo "copying files from $SRC to $OSCMT$SRC"
-tar cf - $FILES | tar xvf - -C $OSCMT || fail "copying $SRC" 10
-
-echo "comparing newly copied files"
-for f in $FILES; do
- diff -q $f $OSCMT/$f || ERROR=11
-done
-
-[ "$ERROR" ] && fail "old and new files are different" 11
-
-sh llcleanup.sh $@
-
-echo | sh llrsetup.sh $@ || exit 20
-echo "comparing previously copied files"
-diff -u /etc/hosts $OSCMT/hosts || fail "$OSCMT/hosts is now different" 21
-
-for f in $FILES; do
- diff -q $f $OSCMT/$f || ERROR=22
-done
-
-[ "$ERROR" ] && fail "old and new files are different on second diff" 23
-
-sh llcleanup.sh $@
-echo | sh llrsetup.sh $@ || exit 24
-
-echo "truncating $OSCMT/hosts"
-> $OSCMT/hosts || fail "can't truncate $OSTMT/hosts" 25
-echo "removing $OSCMT/hosts"
-rm $OSCMT/hosts || fail "can't remove $OSCMT/hosts" 26
-
-echo "removing $OSCMT$SRC"
-rm -r $OSCMT$SRC || fail "can't remove $OSCMT$SRC" 27
-
-sh llcleanup.sh $@
+++ /dev/null
-#!/bin/sh
-vmstat 1 | while read LINE ; do echo "`date +%H:%M:%S`: $LINE" ; done
+++ /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 <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
-/* -*- 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, rc, c, 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
-#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: %s\n", argv[1], strerror(errno));
-
- return err;
-}
+++ /dev/null
-#!/bin/bash
-
-config=uml.xml
-LMC=../utils/lmc
-
-echo "FIXME: autoformat is no by default, edit $config to change"
-
-# create nodes
-${LMC} -o $config --node uml1 --net uml1 tcp
-${LMC} -m $config --node uml2 --net uml2 tcp
-${LMC} -m $config --node uml3 --net uml3 tcp
-
-# configure mds server
-${LMC} -m $config --node uml1 --mds mds1 /tmp/mds1 50000
-
-# configure ost
-${LMC} -m $config --lov lov1 mds1 65536 0 0
-${LMC} -m $config --node uml2 --lov lov1 --ost /tmp/ost1 100000
-${LMC} -m $config --node uml2 --lov lov1 --ost /tmp/ost2 100000
-# is this needed?
-# ${LMC} -m $config --node uml2 --mdc MDC_mds1
-
-# create client config
-${LMC} -m $config --node uml3 --mtpt /mnt/lustre mds1 lov1
-
+++ /dev/null
-<?xml version='1.0' encoding='UTF-8'?>
-<lustre>
- <ldlm name='ldlm' uuid='ldlm_UUID'/>
- <node name='uml1' uuid='uml1_UUID'>
- <profile>
- <ldlm_ref uuidref='ldlm_UUID'/>
- <network_ref uuidref='NET_uml1_tcp_UUID'/>
- <mds_ref uuidref='mds1_UUID'/>
- <lov_ref uuidref='lov1_UUID'/>
- </profile>
- <network name='NET_uml1_tcp' uuid='NET_uml1_tcp_UUID' type='tcp'>
- <server>uml1</server>
- <port>888</port>
- </network>
- </node>
- <node name='uml2' uuid='uml2_UUID'>
- <profile>
- <ldlm_ref uuidref='ldlm_UUID'/>
- <network_ref uuidref='NET_uml2_tcp_UUID'/>
- <obd_ref uuidref='OBD_uml2_UUID'/>
- <ost_ref uuidref='OST_uml2_UUID'/>
- <obd_ref uuidref='OBD_uml2_2_UUID'/>
- <ost_ref uuidref='OST_uml2_2_UUID'/>
- </profile>
- <network uuid='NET_uml2_tcp_UUID' name='NET_uml2_tcp' type='tcp'>
- <server>uml2</server>
- <port>888</port>
- </network>
- </node>
- <node name='uml3' uuid='uml3_UUID'>
- <profile>
- <ldlm_ref uuidref='ldlm_UUID'/>
- <network_ref uuidref='NET_uml3_tcp_UUID'/>
- <mountpoint_ref uuidref='MNT_uml3_UUID'/>
- <mdc_ref uuidref='MDC_mds1_UUID'/>
- </profile>
- <network name='NET_uml3_tcp' uuid='NET_uml3_tcp_UUID' type='tcp'>
- <server>uml3</server>
- <port>888</port>
- </network>
- </node>
- <mds name='mds1' uuid='mds1_UUID'>
- <fstype>extN</fstype>
- <device size='50000'>/tmp/mds1</device>
- <autoformat>yes</autoformat>
- <network_ref uuidref='NET_uml1_tcp_UUID'/>
- <node_ref uuidref='uml1_UUID'/>
- </mds>
- <mdc name='MDC_mds1' uuid='MDC_mds1_UUID'>
- <mds_ref uuidref='mds1_UUID'/>
- </mdc>
- <lov name='lov1' uuid='lov1_UUID'>
- <mds_ref uuidref='mds1_UUID'/>
- <devices stripeoffset='0' stripesize='65536' pattern='0'>
- <osc_ref uuidref='OSC_uml2_UUID'/>
- <osc_ref uuidref='OSC_uml2_2_UUID'/>
- </devices>
- </lov>
- <obd uuid='OBD_uml2_UUID' name='OBD_uml2' type='obdfilter'>
- <fstype>extN</fstype>
- <device size='100000'>/tmp/ost1</device>
- <autoformat>yes</autoformat>
- </obd>
- <osc name='OSC_uml2' uuid='OSC_uml2_UUID'>
- <ost_ref uuidref='OST_uml2_UUID'/>
- <obd_ref uuidref='OBD_uml2_UUID'/>
- </osc>
- <ost name='OST_uml2' uuid='OST_uml2_UUID'>
- <network_ref uuidref='NET_uml2_tcp_UUID'/>
- <obd_ref uuidref='OBD_uml2_UUID'/>
- </ost>
- <obd name='OBD_uml2_2' uuid='OBD_uml2_2_UUID' type='obdfilter'>
- <fstype>extN</fstype>
- <device size='100000'>/tmp/ost2</device>
- <autoformat>yes</autoformat>
- </obd>
- <osc name='OSC_uml2_2' uuid='OSC_uml2_2_UUID'>
- <ost_ref uuidref='OST_uml2_2_UUID'/>
- <obd_ref uuidref='OBD_uml2_2_UUID'/>
- </osc>
- <ost name='OST_uml2_2' uuid='OST_uml2_2_UUID'>
- <network_ref uuidref='NET_uml2_tcp_UUID'/>
- <obd_ref uuidref='OBD_uml2_2_UUID'/>
- </ost>
- <mountpoint name='MNT_uml3' uuid='MNT_uml3_UUID'>
- <mdc_ref uuidref='MDC_mds1_UUID'/>
- <osc_ref uuidref='lov1_UUID'/>
- <path>/mnt/lustre</path>
- </mountpoint>
-</lustre>
+++ /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
+++ /dev/null
-# Administration utilities Makefile
-DEFS=
-
-CFLAGS:=-g -O2 -I. -I$(PORTALS)/include -I$(srcdir)/../include -Wall\
- -L$(PORTALS)/linux/utils
-KFLAGS:=
-CPPFLAGS = $(HAVE_LIBREADLINE)
-obdctl_LDADD := $(LIBREADLINE)
-lctl_LDADD := $(LIBREADLINE) -lptlctl
-sbin_PROGRAMS = lctl obdctl
-obdctl_SOURCES = parser.c obdctl.c obd.c parser.h obdctl.h
-lctl_SOURCES = parser.c obd.c lctl.c parser.h
-
-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 2432
-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
-import re, exceptions
-import xml.dom.minidom
-
-# Global parameters
-TCP_ACCEPTOR = '../..//portals/linux/utils/acceptor'
-options = {}
-
-#
-# Maximum number of devices to search for.
-# (the /dev/loop* nodes need to be created beforehand)
-MAX_LOOP_DEVICES = 256
-
-
-def usage():
- print """usage: lconf config.xml
-
-config.xml Lustre configuration in xml format.
---get <url> URL to fetch a config file
--v | --verbose Print system commands as they are run
--d | --debug Print system commands, but does not run them
---host <hostname> Load config for <hostname>
---cleanup Cleans up config. (Shutdown)
--h | --help Print this help
-"""
- TODO = """
---ldap server LDAP server with lustre config database
---reformat Reformat all devices (will confirm)
---lustre="src dir" Base directory of lustre sources. Used to search
- for modules.
---portals=src Portals source
---makeldiff Translate xml source to LDIFF
---iam myname ??
-"""
- sys.exit()
-
-# ============================================================
-# debugging and error funcs
-
-def fixme(msg = "this feature"):
- raise RuntimeError, msg + ' not implmemented yet.'
-
-def panic(*args):
- msg = string.join(map(str,args))
- print msg
- raise RuntimeError, 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):
- msg = string.join(map(str,args))
- if isverbose(): print msg
-
-def isverbose():
- return options.has_key('verbose') and options['verbose'] == 1
-
-def isnotouch():
- return options.has_key('debug') and options['debug'] == 1
-
-# ============================================================
-# locally defined exceptions
-class CommandError (exceptions.Exception):
- def __init__(self, args=None):
- self.args = args
-
-# ============================================================
-# handle lctl interface
-class LCTLInterface:
- """
- Manage communication with lctl
- """
-
- def __init__(self, cmd):
- """
- Initialize close by finding the lctl binary.
- """
- syspath = string.split(os.environ['PATH'], ':')
- syspath.insert(0, "../utils");
- self.lctlcmd = None
- for d in syspath:
- lctl = os.path.join(d,cmd)
- if os.access(lctl, os.X_OK):
- self.lctl = lctl
- break
- if not self.lctl:
- raise RuntimeError, "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 isnotouch(): return ([], 0)
- p = popen2.Popen3(self.lctl, 1)
- p.tochild.write(cmds + "\n")
- p.tochild.close()
- out = p.fromchild.readlines()
- ret = p.poll()
- for l in out:
- debug('lctl:',string.strip(l))
- err = p.childerr.readlines()
- if ret or len(err):
- log (self.lctl, "error:", ret)
- logall(err)
- raise CommandError, err
- return ret, 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 == 'tcp':
- 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_buf, read_buf):
- # XXX: buf size params not used yet
- cmds = """
- network %s
- connect %s %d
- add_uuid %s %s
- quit""" % (net, nid, port, servuuid, nid)
- self.run(cmds)
-
- # create a new connection
- def add_route(self, net, to, via):
- cmds = """
- """
- #self.run(cmds)
-
- # create a new device with lctl
- def disconnect(self, net, nid, port, servuuid):
- cmds = """
- network %s
- disconnect %s
- quit""" % (net, nid)
- 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 = """
- device $%s
- cleanup
- detach
- quit""" % (name)
- self.run(cmds)
-
- # create an lov
- def lovconfig(self, uuid, mdsuuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist):
- cmds = """
- device $%s
- probe
- lovconfig %s %d %d %d %s %s
- quit""" % (mdsuuid, uuid, stripe_cnt, stripe_sz, stripe_off, pattern, devlist)
- self.run(cmds)
-
-# ============================================================
-# 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 isnotouch(): 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 isnotouch(): return 0
- f = os.popen(cmd + ' 2>&1')
- ret = f.close()
- if ret:
- ret = ret >> 8
- else:
- ret = 0
- return ret
-
-
-# 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)
-
-# 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 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)
-
-# initialize a block device if needed
-def block_dev(dev, size, fstype, format):
- if isnotouch(): return dev
- if not is_block(dev):
- dev = init_loop(dev, size, fstype)
- if (format == 'yes'):
- mkfs(fstype, dev)
- return dev
-
-# ============================================================
-# 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, tag_name, node):
- self.dom_node = node
- self.tag_name = tag_name
- self.name = node.getAttribute('name')
- self.uuid = node.getAttribute('uuid')
-
- def info(self, *args):
- msg = string.join(map(str,args))
- print self.tag_name + ":", self.name, self.uuid, msg
-
- def cleanup(self):
- """ default cleanup, used for most modules """
- self.info()
- try:
- lctl.cleanup(self.name, self.uuid)
- except CommandError:
- print "cleanup failed: ", self.name
-
-class Network(Module):
- def __init__(self,node):
- Module.__init__(self, 'NETWORK', node)
- self.net_type = node.getAttribute('type')
- self.nid = getText(node, 'server', "")
- self.port = int(getText(node, 'port', 0))
- self.send_buf = int(getText(node, 'send_buf', 0))
- self.read_buf = int(getText(node, 'read_buf', 0))
-
- def prepare(self):
- self.info(self.net_type, self.nid, self.port)
- if self.net_type == 'tcp':
- ret = run_daemon(TCP_ACCEPTOR, self.port)
- if ret:
- print "error:", ret
- raise CommandError, "cannot run acceptor"
- lctl.network(self.net_type, self.nid)
- lctl.newdev(attach = "ptlrpc RPCDEV")
-
- def cleanup(self):
- self.info(self.net_type, self.nid, self.port)
- try:
- lctl.cleanup("RPCDEV", "")
- except CommandError:
- print "cleanup failed: ", self.name
- if self.net_type == 'tcp':
- # yikes, this ugly! need to save pid in /var/something
- run("killall acceptor")
-
-class LDLM(Module):
- def __init__(self,node):
- Module.__init__(self, 'LDLM', node)
- def prepare(self):
- self.info()
- lctl.newdev(attach="ldlm %s %s" % (self.name, self.uuid),
- setup ="")
-
-class LOV(Module):
- def __init__(self,node):
- Module.__init__(self, 'LOV', node)
- devs = node.getElementsByTagName('devices')[0]
- self.stripe_sz = int(devs.getAttribute('stripesize'))
- self.stripe_off = int(devs.getAttribute('stripeoffset'))
- self.pattern = int(devs.getAttribute('pattern'))
- mdsref = node.getElementsByTagName('mds_ref')[0]
- self.mdsuuid = mdsref.getAttribute('uuidref')
- mds= lookup(node.parentNode, self.mdsuuid)
- self.mdsname = getName(mds)
- devlist = ""
- stripe_cnt = 0
- for child in devs.childNodes:
- if child.nodeName == 'osc_ref':
- devlist = devlist + child.getAttribute('uuidref') + " "
- strip_cnt = stripe_cnt + 1
- self.devlist = devlist
- self.stripe_cnt = strip_cnt
-
- def prepare(self):
- self.info(self.mdsuuid, self.stripe_cnt, self.stripe_sz, self.stripe_off, self.pattern,
- self.devlist, self.mdsname)
- lctl.lovconfig(self.uuid, self.mdsname, self.stripe_cnt,
- self.stripe_sz, self.stripe_off, self.pattern,
- self.devlist)
-
-class MDS(Module):
- def __init__(self,node):
- Module.__init__(self, 'MDS', node)
- self.devname, self.size = getDevice(node)
- self.fstype = getText(node, 'fstype')
- self.format = getText(node, 'autoformat', "no")
-
- def prepare(self):
- self.info(self.devname, self.fstype, self.format)
- blkdev = block_dev(self.devname, self.size, self.fstype, self.format)
- lctl.newdev(attach="mds %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(blkdev, self.fstype))
- def cleanup(self):
- Module.cleanup(self)
- clean_loop(self.devname)
-
-class MDC(Module):
- def __init__(self,node):
- Module.__init__(self, 'MDC', node)
- ref = node.getElementsByTagName('mds_ref')[0]
- self.mds_uuid = ref.getAttribute('uuidref')
-
- def prepare(self):
- self.info(self.mds_uuid)
- mds = lookup(self.dom_node.parentNode, self.mds_uuid)
- if mds == None:
- panic(self.mdsuuid, "not found.")
- net = get_ost_net(self.dom_node.parentNode, self.mds_uuid)
- srv = Network(net)
- lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_buf, srv.read_buf)
- lctl.newdev(attach="mdc %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(self.mds_uuid, srv.uuid))
-
- def cleanup(self):
- self.info(self.mds_uuid)
- net = get_ost_net(self.dom_node.parentNode, self.mds_uuid)
- srv = Network(net)
- try:
- lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
- lctl.cleanup(self.name, self.uuid)
- except CommandError:
- print "cleanup failed: ", self.name
-
-class OBD(Module):
- def __init__(self, node):
- Module.__init__(self, 'OBD', node)
- self.obdtype = node.getAttribute('type')
- self.devname, self.size = getDevice(node)
- self.fstype = getText(node, 'fstype')
- self.format = getText(node, 'autoformat', 'yes')
-
- # need to check /proc/mounts and /etc/mtab before
- # formatting anything.
- # FIXME: check if device is already formatted.
- def prepare(self):
- self.info(self.obdtype, self.devname, self.size, self.fstype, self.format)
- 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):
- Module.cleanup(self)
- clean_loop(self.devname)
-
-class OST(Module):
- def __init__(self,node):
- Module.__init__(self, 'OST', node)
- ref = node.getElementsByTagName('obd_ref')[0]
- self.obd_uuid = ref.getAttribute('uuidref')
-
- def prepare(self):
- self.info(self.obd_uuid)
- lctl.newdev(attach="ost %s %s" % (self.name, self.uuid),
- setup ="%s" % (self.obd_uuid))
-
-class OSC(Module):
- def __init__(self,node):
- Module.__init__(self, 'OSC', node)
- ref = node.getElementsByTagName('obd_ref')[0]
- self.obd_uuid = ref.getAttribute('uuidref')
- ref = node.getElementsByTagName('ost_ref')[0]
- self.ost_uuid = ref.getAttribute('uuidref')
-
- def prepare(self):
- self.info(self.obd_uuid, self.ost_uuid)
- net = get_ost_net(self.dom_node.parentNode, self.ost_uuid)
- srv = Network(net)
- lctl.connect(srv.net_type, srv.nid, srv.port, srv.uuid, srv.send_buf, srv.read_buf)
- lctl.newdev(attach="osc %s %s" % (self.name, self.uuid),
- setup ="%s %s" %(self.obd_uuid, srv.uuid))
-
- def cleanup(self):
- self.info(self.obd_uuid, self.ost_uuid)
- net_uuid = get_ost_net(self.dom_node.parentNode, self.ost_uuid)
- srv = Network(net)
- try:
- lctl.disconnect(srv.net_type, srv.nid, srv.port, srv.uuid)
- lctl.cleanup(self.name, self.uuid)
- except CommandError:
- print "cleanup failed: ", self.name
-
-class Mountpoint(Module):
- def __init__(self,node):
- Module.__init__(self, 'MTPT', node)
- self.path = getText(node, 'path')
- ref = node.getElementsByTagName('mdc_ref')[0]
- self.mdc_uuid = ref.getAttribute('uuidref')
- ref = node.getElementsByTagName('osc_ref')[0]
- self.lov_uuid = ref.getAttribute('uuidref')
-
- def prepare(self):
- l = lookup(self.dom_node.parentNode, self.lov_uuid)
- if l.nodeName == 'lov':
- dev = LOV(l)
- for osc_uuid in string.split(dev.devlist):
- osc = lookup(self.dom_node.parentNode, osc_uuid)
- if osc:
- n = OSC(osc)
- n.prepare()
- else:
- panic('osc not found:', osc_uuid)
- else:
- dev = OSC(l)
- dev.prepare()
-
- self.info(self.path, self.mdc_uuid,self.lov_uuid)
- lctl.newdev(attach="lov %s %s" % (dev.name, dev.uuid),
- setup ="%s" % (self.mdc_uuid))
- cmd = "mount -t lustre_lite -o osc=%s,mdc=%s none %s" % \
- (self.lov_uuid, self.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.mdc_uuid,self.lov_uuid)
- run("umount", self.path)
-
-# ============================================================
-# XML processing and query
-# TODO: Change query funcs to use XPath, which is muc cleaner
-
-def getDevice(obd):
- dev = obd.getElementsByTagName('device')[0]
- dev.normalize();
- try:
- size = int(dev.getAttribute('size'))
- except ValueError:
- size = 0
- return dev.firstChild.data, size
-
-# Get the text content from the first matching child
-def getText(node, tag, default=""):
- list = node.getElementsByTagName(tag)
- if len(list) > 0:
- node = list[0]
- node.normalize()
- return node.firstChild.data
- else:
- return default
-
-def get_ost_net(node, uuid):
- ost = lookup(node, uuid)
- list = ost.getElementsByTagName('network_ref')
- if list:
- uuid = list[0].getAttribute('uuidref')
- else:
- return None
- return lookup(node, uuid)
-
-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
-
-# Get name attribute of node
-def getName(node):
- return node.getAttribute('name')
-
-def getRef(node):
- return node.getAttribute('uuidref')
-
-# Get name attribute of node
-def getUUID(node):
- return node.getAttribute('uuid')
-
-# the tag name is the service type
-# fixme: this should do some checks to make sure the node is a service
-def getServiceType(node):
- return node.nodeName
-
-#
-# determine what "level" a particular node is at.
-# the order of iniitailization is based on level. objects
-# are assigned a level based on type:
-# net,devices,ldlm:1, obd, mdd:2 mds,ost:3 osc,mdc:4 mounts:5
-def getServiceLevel(node):
- type = getServiceType(node)
- if type in ('network',):
- return 1
- if type in ('device', 'ldlm'):
- return 2
- elif type in ('obd', 'mdd'):
- return 3
- elif type in ('mds','ost'):
- return 4
- elif type in ('mdc','osc'):
- return 5
- elif type in ('lov',):
- return 6
- elif type in ('mountpoint',):
- return 7
- return 0
-
-#
-# return list of services in a profile. list is a list of tuples
-# [(level, 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)
- list.append((level, servNode))
- list.sort()
- return list
-
-def getByName(lustreNode, tag, name):
- ndList = lustreNode.getElementsByTagName(tag)
- for nd in ndList:
- if getName(nd) == name:
- return nd
- return None
-
-
-# ============================================================
-# lconf level logic
-# Start a service.
-def startService(node, cleanFlag):
- type = getServiceType(node)
- debug('Starting service:', type, getName(node), getUUID(node))
- # there must be a more dynamic way of doing this...
- n = None
- if type == 'ldlm':
- n = LDLM(node)
- elif type == 'lov':
- n = LOV(node)
- elif type == 'network':
- n = Network(node)
- elif type == 'obd':
- n = OBD(node)
- elif type == 'ost':
- n = OST(node)
- elif type == 'mds':
- n = MDS(node)
- elif type == 'osc':
- n = OSC(node)
- elif type == 'mdc':
- n = MDC(node)
- elif type == 'mountpoint':
- n = Mountpoint(node)
- else:
- panic ("unknown service type:", type)
-
- if cleanFlag:
- 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, cleanFlag):
- if not profileNode:
- panic("profile:", profile, "not found.")
- services = getServices(lustreNode, profileNode)
- if cleanFlag:
- services.reverse()
- for s in services:
- startService(s[1], cleanFlag)
-
-#
-# Load profile for
-def doHost(lustreNode, hosts, cleanFlag):
- node = None
- for h in hosts:
- node = getByName(lustreNode, 'node', h)
- if node:
- break
-
- if not node:
- print 'No host entry found.'
- return
-
- reflist = node.getElementsByTagName('profile')
- for profile in reflist:
- startProfile(lustreNode, profile, cleanFlag)
-
-# Command line processing
-#
-def parse_cmdline(argv):
- short_opts = "hdv"
- long_opts = ["ldap", "reformat", "lustre=", "verbose",
- "portals=", "makeldiff", "cleanup", "iam=",
- "help", "debug", "host=", "get="]
- opts = []
- args = []
- global options
- try:
- opts, args = getopt.getopt(argv, short_opts, long_opts)
- except getopt.GetoptError:
- print "invalid opt"
- usage()
-
- for o, a in opts:
- if o in ("-h", "--help"):
- usage()
- if o == "--cleanup":
- options['cleanup'] = 1
- if o in ("-v", "--verbose"):
- options['verbose'] = 1
- if o in ("-d", "--debug"):
- options['debug'] = 1
- options['verbose'] = 1
- if o == "--portals":
- options['portals'] = a
- if o == "--lustre":
- options['lustre'] = a
- if o == "--reformat":
- options['reformat'] = 1
- if o == "--host":
- options['hostname'] = [a]
- if o == "--get":
- options['url'] = a
- return args
-
-def fetch(url):
- import urllib
- data = ""
- try:
- s = urllib.urlopen(url)
- data = s.read()
- except:
- usage()
- return data
-
-# Initialize or shutdown lustre according to a configuration file
-# * prepare the system for lustre
-# * configure devices with lctl
-# Shutdown does steps in reverse
-#
-lctl = LCTLInterface('lctl')
-def main():
- global options
- args = parse_cmdline(sys.argv[1:])
- if len(args) > 0:
- if not os.access(args[0], os.R_OK | os.W_OK):
- print 'File not found:', args[0]
- sys.exit(1)
- dom = xml.dom.minidom.parse(args[0])
- elif options.has_key('url'):
- xmldata = fetch(options['url'])
- dom = xml.dom.minidom.parseString(xmldata)
- else:
- usage()
-
- if not options.has_key('hostname'):
- options['hostname'] = []
- host = socket.gethostname()
- if len(host) > 0:
- options['hostname'].append(host)
- options['hostname'].append('localhost')
- print "configuring for host: ", options['hostname']
- doHost(dom.documentElement, options['hostname'], options.has_key('cleanup') )
-
-if __name__ == "__main__":
- main()
+++ /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;
-}
-
-command_t cmdlist[] = {
- /* Metacommands */
- {"--device", jt_opt_device, 0, "--device <devno> <command [args ...]>"},
- {"--threads", jt_opt_threads, 0,
- "--threads <threads> <devno> <command [args ...]>"},
-
- /* Network configuration commands */
- {"==== network config ====", jt_noop, 0, "network config"},
- {"network", jt_ptl_setup, 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>"},
- {"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 a uuid and make it the current device\n"
- "usage: uuid2dev <uuid>"},
-#endif
- {"name2dev", jt_obd_name2dev, 0,
- "find a 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"},
-
- /* Device configuration commands */
- {"==== device config =====", jt_noop, 0, "device config"},
- {"attach", jt_obd_attach, 0, "name and type the device\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 setup\n"
- "usage: cleanup"},
- {"detach", jt_obd_detach, 0, "un-name a device\n"
- "usage: detach"},
- {"lovconfig", jt_obd_lov_config, 0,
- "write lov configuration to an mds device\n"
- "usage: lovconfig lov-uuid stripe-count stripe-size offset pattern UUID1 [UUID2 ...]"},
-
- /* 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 too "
- "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 id\n"
- "usage: getattr <id>"},
- {"setattr", jt_obd_setattr, 0, "set attribute for id\n"
- "usage: setattr <id> <mode>"},
- {"test_getattr", jt_obd_test_getattr, 0,
- "perform count number of getattr's\n"
- "usage: test_getattr <count> [verbose]"},
- {"test_brw", jt_obd_test_brw, 0,
- "perform count number of bulk read/writes\n"
- "usage: test_brw <count> [write [verbose [pages [obdos]]]]"},
- {"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 (usage: ldlm_regress_start "
- "[numthreads])\n"},
- {"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)"},
-
-#if 0
- {"create", jt_create, 0, "create [count [mode [verbose]]]"},
- {"destroy", jt_destroy, 0, "destroy <id>"},
- {"newconn", jt_newconn, 0, "newconn [newuuid]"},
-#endif
- /* 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);
-
- if (ptl_initialize(argc, argv) < 0)
- exit(1);
- 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
-#!/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
-
-
-# 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, getopt, string
-import xml.dom.minidom
-from xml.dom.ext import PrettyPrint
-
-
-DEFAULT_PORT = 888 # 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. When used with other
- commands it specifies the node to modify
-
---net hostname nettype [port, recv_buf, send_buf]
- Nettype is either tcp, elan, or gm.
- Requires a node argument
-
---lov lov_name [mdc_name stripe_sz stripe_off pattern]
- Creates a logical volume
- When used with other commands, it specifics the lov to modify
-
---mds device [size]
- Create a MDS using the device
- Requires --node
-
---mdc mdc_name
- Configures a MDC for a node.
- Requires --node
-
---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
- If --lov lov_name is used, this device is added to lov.
-
---mtpt /mnt/point mdc_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
---reformat Reformat partitions (this should be an lconf arg,
- I think)
-"""
- sys.exit(1)
-
-def error(*args):
- msg = string.join(map(str,args))
- print msg
- sys.exit(1)
-
-#
-# 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 get_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)
-
-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):
- """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))
- return network
-
- 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, devname, format, dev_size=0):
- obd = self.newService("obd", name, uuid)
- obd.setAttribute('type', 'obdfilter')
- self.addElement(obd, "fstype", fs)
- 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_off, 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("stripeoffset", stripe_off)
- devs.setAttribute("pattern", pattern)
- return lov
-
- 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 mdc(self, name, uuid, mds_uuid):
- mdc = self.newService("mdc", name, uuid)
- mdc.appendChild(self.ref("mds", mds_uuid))
- return mdc
-
- def mountpoint(self, name, uuid, mdc_uuid, osc_uuid, path):
- mtpt = self.newService("mountpoint", name, uuid)
- mtpt.appendChild(self.ref("mdc", mdc_uuid))
- mtpt.appendChild(self.ref("osc", osc_uuid))
- self.addElement(mtpt, "path", path)
- return mtpt
-
-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("no node found for:", mds_name)
- node_uuid = ref[0].getAttribute('uuidref')
- node = lookup(lustre, node_uuid)
- if not node:
- error("no node found for :", mds_name)
- return node
-
-def name2uuid(lustre, name, tag="", fatal=1):
- ret = findByName(lustre, name, tag)
- if not ret and fatal:
- error('name2uuid:', name, "not found.")
- 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 ("node not found:", node_name)
- 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))
-
-#
-# Create a new obd, osc, and ost. Add them to the DOM.
-#
-def add_ost(gen, lustre, options, args):
- if len(args) < 1:
- usage()
-
- if options.has_key('node'):
- node_name = options['node']
- else:
- error("--ost requires a --node argument")
-
- if options.has_key('lov'):
- lovname = options['lov']
- else:
- lovname = ''
-
- devname = args[0]
- if len(args) > 1:
- size = args[1]
- else:
- size = 0
-
- obdname = new_name('OBD_'+ node_name)
- oscname = new_name('OSC_'+ node_name)
- ostname = new_name('OST_'+ node_name)
- obd_uuid = get_uuid(obdname)
- ost_uuid = get_uuid(ostname)
- osc_uuid = get_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, "extN", devname, "no", 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("LOV:", lovname, "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)
-
-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]
-
- if net_type == 'tcp':
- if len(args) > 2:
- port = int(args[2])
- else:
- port = DEFAULT_PORT
- # add send, recv buffer size here
- 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, node_name)
- else:
- node = ret
- net_name = new_name('NET_'+ node_name +'_'+ net_type)
- net_uuid = get_uuid(net_name)
- node.appendChild(gen.network(net_name, net_uuid, nid, net_type, port))
- node_add_profile(gen, node, "network", net_uuid)
-
-def do_add_node(gen, lustre, node_name):
- uuid = get_uuid(node_name)
- node = gen.node(node_name, uuid)
- node_add_profile(gen, node, 'ldlm', ldlm_uuid)
- 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, node_name)
-
-
-def add_lov(gen, lustre, options, args):
- """ create a lov """
- if len(args) < 4:
- usage()
-
- name = options['lov']
- mds_name = args[0]
- stripe_sz = args[1]
- stripe_off = args[2]
- pattern = args[3]
- uuid = get_uuid(name)
-
- ret = findByName(lustre, name, "lov")
- if ret:
- error("LOV: ", name, " already exists.")
-
- mds_uuid = name2uuid(lustre, mds_name)
-
- node = mds2node(lustre, mds_name)
- node_add_profile(gen, node, "lov", uuid)
- lov = gen.lov(name, uuid, mds_uuid, stripe_sz, stripe_off, pattern)
- lustre.appendChild(lov)
-
-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]
- mdc_name = 'MDC_' + mds_name
-
- name = new_name('MNT_'+ node_name)
-
- ret = findByName(lustre, name, "mountpoint")
- if ret:
- error("MOUNTPOINT: ", name, " already exists.")
-
- lov_uuid = name2uuid(lustre, lov_name)
- mdc_uuid = name2uuid(lustre, mdc_name)
-
- uuid = get_uuid(name)
- mtpt = gen.mountpoint(name, uuid, mdc_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)
- node_add_profile(gen, node, "mdc", mdc_uuid)
- lustre.appendChild(mtpt)
-
-def add_mdc(gen, lustre, options, args):
- """ create mtpt on a node """
- if len(args) < 1:
- usage()
-
- if options.has_key('node'):
- node_name = options['node']
- else:
- error("--mdc requires a --node argument")
-
- mdc_name = args[0]
- mdc_uuid = name2uuid(lustre, mdc_name)
-
- node = findByName(lustre, node_name, "node")
- if not node:
- error('node:', node_name, "not found.")
- node_add_profile(gen, node, "mdc", mdc_uuid)
-
-def add_mds(gen, lustre, options, args):
- if len(args) < 1:
- usage()
-
- if options.has_key('node'):
- node_name = options['node']
- else:
- error("--mds requires a --node argument")
-
- mds_name = new_name(options['mds'])
- devname = args[0]
- if len(args) > 1:
- size = args[1]
- else:
- size = 0
-
- mdc_name = 'MDC_' + mds_name
- mds_uuid = get_uuid(mds_name)
- mdc_uuid = get_uuid(mdc_name)
-
- node_uuid = name2uuid(lustre, node_name)
-
- 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, "extN", devname, "no", net_uuid, node_uuid, dev_size=size)
- mdc = gen.mdc(mdc_name, mdc_uuid, mds_uuid)
- lustre.appendChild(mds)
- lustre.appendChild(mdc)
-
-
-#
-# Command line processing
-#
-
-def parse_cmdline(argv):
- short_opts = "ho:i:m:"
- long_opts = ["ost", "mtpt", "lov=", "node=", "mds=", "net",
- "mdc", "merge=", "format", "reformat", "output=",
- "in=", "help"]
- opts = []
- args = []
- options = {}
- try:
- opts, args = getopt.getopt(argv, short_opts, long_opts)
- except getopt.GetoptError:
- print "invalid opt"
- usage()
-
- for o, a in opts:
- if o in ("-h", "--help"):
- usage()
- if o in ("-o", "--output"):
- options['output'] = a
- if o == "--ost":
- options['ost'] = 1
- if o == "--mds":
- options['mds'] = a
- if o == "--mdc":
- options['mdc'] = 1
- if o == "--net":
- options['net'] = 1
- if o == "--mtpt":
- options['mtpt'] = 1
- if o == "--node":
- options['node'] = a
- if o == "--lov":
- options['lov'] = a
- if o in ("-m", "--merge"):
- options['merge'] = a
- if o == "--format":
- options['format'] = 1
- if o == "--reformat":
- options['reformat'] = 1
- if o in ("--in" , "-i"):
- options['in'] = a
-
- return options, args
-
-
-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
-
-
-def main():
- options, args = parse_cmdline(sys.argv[1:])
- outFile = '-'
-
- if options.has_key('merge'):
- outFile = options['merge']
- doc = xml.dom.minidom.parse(outFile)
- 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('ost'):
- add_ost(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('mdc'):
- add_mdc(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('node'):
- add_node(gen, lustre, options, args)
- else:
- print "Missing command"
- usage()
-
- if outFile == '-':
- PrettyPrint(doc)
- else:
- PrettyPrint(doc, open(outFile,"w"))
-
-if __name__ == "__main__":
- main()
-
-
+++ /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 | profile | mountpoint | ldlm |\r
- mds | mdc | obd | ost | osc | lov | router)*>\r
-\r
-<!ELEMENT profile (service_ref)*>\r
-<!ATTLIST profile %tag.attr;>\r
-<!ELEMENT mountpoint (path | fileset | mdc_ref | osc_ref)*>\r
-<!ATTLIST mountpoint %tag.attr;>\r
-<!ELEMENT node (network*, profile_ref)>\r
-<!ATTLIST node %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 | obdext2 | obdecho) 'obdfilter'>\r
-<!ELEMENT ost (network_ref | obd_ref | failover_ref)*>\r
-<!ATTLIST ost %tag.attr;>\r
-<!ELEMENT mds (network_ref | fstype | device | autoformat | server_ref | failover_ref)*>\r
-<!ATTLIST mds %tag.attr;>\r
-\r
-<!ELEMENT osc (network_ref | obd_ref)*>\r
-<!ATTLIST osc %tag.attr;>\r
-<!ELEMENT mdc (network_ref | mds_ref)*>\r
-<!ATTLIST mdc %tag.attr;>\r
-<!ELEMENT lov (devices | mdc_ref)*>\r
-<!ATTLIST lov %tag.attr;>\r
-<!ELEMENT devices (osc_ref)+>\r
-<!ATTLIST devices stripesize CDATA #REQUIRED\r
- stripeoffset CDATA #REQUIRED\r
- pattern CDATA #REQUIRED>\r
-<!ELEMENT router (misc)*>\r
-<!ATTLIST router %tag.attr;>\r
-\r
-<!-- basic elements -->\r
-<!ELEMENT network (server | port)*>\r
-<!ATTLIST network type (tcp | elan | myrinet) 'tcp'\r
- %tag.attr;>\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 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 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 lov_ref %tag.content;>\r
-<!ATTLIST lov_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 service_ref %tag.content;>\r
-<!ATTLIST service_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
-\r
+++ /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 <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 <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 = 8192;
-
-static int thread;
-
-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)
-
-/*
- pack "LL LL LL LL LL LL LL L L L L L L L L L a60 a60 L L L",
- $obdo->{id}, 0,
- $obdo->{gr}, 0,
- $obdo->{atime}, 0,
- $obdo->{mtime}, 0 ,
- $obdo->{ctime}, 0,
- $obdo->{size}, 0,
- $obdo->{blocks}, 0,
- $obdo->{blksize},
- $obdo->{mode},
- $obdo->{uid},
- $obdo->{gid},
- $obdo->{flags},
- $obdo->{obdflags},
- $obdo->{nlink},
- $obdo->{generation},
- $obdo->{valid},
- $obdo->{inline},
- $obdo->{obdmd},
- 0, 0, # struct list_head
- 0; # struct obd_ops
-}
-
-*/
-
-char *obdo_print(struct obdo *obd)
-{
- char buf[1024];
-
- sprintf(buf, "id: %Ld\ngrp: %Ld\natime: %Ld\nmtime: %Ld\nctime: %Ld\n"
- "size: %Ld\nblocks: %Ld\nblksize: %d\nmode: %o\nuid: %d\n"
- "gid: %d\nflags: %x\nobdflags: %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 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;
-
- if (obd_ioctl_pack(&data, &buf, max)) {
- fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(func));
- return -2;
- }
- 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;
- }
-
- memcpy((char *)(&data), buf, sizeof(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,
- int num, int *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(const char *arg)
-{
- int verbose;
-
- if (!arg || arg[0] == 'v')
- verbose = 1;
- else if (arg[0] == 's' || arg[0] == 'q')
- verbose = 0;
- else
- verbose = (int)strtoul(arg, NULL, 0);
-
- 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: %x %s\n", cmdname(func),
- OBD_IOC_DISCONNECT, strerror(errno));
- } else {
- if (verbose)
- printf("%s: disconnected conn %Lx\n", cmdname(func),
- conn_addr);
- conn_addr = -1;
- }
-
- return rc;
-}
-
-#if SHMEM_STATS
-static void shmem_setup(void)
-{
- 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;
- }
-
- 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;
- }
-}
-
-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;
-
- if (obd_ioctl_pack(&data, &buf, max)) {
- fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(func));
- return -2;
- }
-
- 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);
-
- if (argc != 1)
- return CMD_HELP;
-
- rc = ioctl(fd, OBD_IOC_CONNECT, &data);
- if (rc < 0)
- fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
- OBD_IOC_CONNECT, 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) {
- fprintf(stderr, "usage: %s devno <command [args ...]>\n",
- cmdname(argv[0]));
- return -1;
- }
-
- 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)
-{
- int threads, next_thread;
- int verbose;
- int rc = 0;
- int i;
-
- if (argc < 5) {
- fprintf(stderr,
- "usage: %s numthreads verbose devno <cmd [args ...]>\n",
- argv[0]);
- return -1;
- }
-
- threads = strtoul(argv[1], NULL, 0);
-
- verbose = get_verbose(argv[2]);
-
- if (verbose != 0)
- printf("%s: starting %d 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)
- 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;
- int rc;
-
- IOCINIT(data);
-
- if (argc != 1)
- return CMD_HELP;
-
- if (obd_ioctl_pack(&data, &buf, max)) {
- fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
- return -2;
- }
-
- 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_obd_list(int argc, char **argv)
-{
- int rc;
- char buf[1024];
- 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];
- }
-
- if (obd_ioctl_pack(&data, &buf, max)) {
- fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
- return -2;
- }
-
- rc = ioctl(fd, OBD_IOC_ATTACH, buf);
- if (rc < 0)
- fprintf(stderr, "error: %s: %x %s\n", cmdname(argv[0]),
- OBD_IOC_ATTACH, 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];
- }
-
- if (obd_ioctl_pack(&data, &buf, max)) {
- fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
- return -2;
- }
- rc = ioctl(fd, OBD_IOC_SETUP, buf);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
-
- return rc;
-}
-
-
-int jt_obd_create(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- struct timeval next_time;
- int count = 1, next_count;
- int verbose;
- int rc = 0, i;
-
- IOCINIT(data);
- if (argc < 2 || argc > 4) {
- fprintf(stderr, "usage: %s num [mode] [verbose]\n",
- cmdname(argv[0]));
- return -1;
- }
- count = strtoul(argv[1], NULL, 0);
-
- if (argc > 2)
- data.ioc_obdo1.o_mode = strtoul(argv[2], NULL, 0);
- else
- data.ioc_obdo1.o_mode = 0100644;
- data.ioc_obdo1.o_valid = OBD_MD_FLMODE;
-
- verbose = get_verbose(argv[3]);
-
- printf("%s: %d obdos\n", cmdname(argv[0]), count);
- gettimeofday(&next_time, NULL);
- next_time.tv_sec -= verbose;
-
- for (i = 1, next_count = verbose; i <= count; i++) {
- rc = ioctl(fd, OBD_IOC_CREATE, &data);
- SHMEM_BUMP();
- if (rc < 0) {
- fprintf(stderr, "error: %s: #%d - %s\n",
- cmdname(argv[0]), i, strerror(rc = errno));
- break;
- }
- if (be_verbose(verbose, &next_time, i, &next_count, count))
- printf("%s: #%d is object id %Ld\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;
- int rc;
-
- IOCINIT(data);
- if (argc != 2)
- return CMD_HELP;
-
- data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
- data.ioc_obdo1.o_mode = S_IFREG | strtoul(argv[2], NULL, 0);
- data.ioc_obdo1.o_valid = OBD_MD_FLMODE;
-
- rc = ioctl(fd, OBD_IOC_SETATTR, &data);
- 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;
- int rc;
-
- IOCINIT(data);
- if (argc != 2) {
- fprintf(stderr, "usage: %s id\n", cmdname(argv[0]));
- return -1;
- }
-
- data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
- data.ioc_obdo1.o_mode = S_IFREG | 0644;
-
- rc = ioctl(fd, OBD_IOC_DESTROY, &data);
- if (rc < 0)
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
-
- return rc;
-}
-
-int jt_obd_getattr(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- int rc;
-
- if (argc != 2)
- return CMD_HELP;
-
- IOCINIT(data);
- data.ioc_obdo1.o_id = strtoul(argv[1], NULL, 0);
- /* to help obd filter */
- data.ioc_obdo1.o_mode = 0100644;
- data.ioc_obdo1.o_valid = 0xffffffff;
- printf("%s: object id %Ld\n", cmdname(argv[0]), data.ioc_obdo1.o_id);
-
- rc = ioctl(fd, OBD_IOC_GETATTR, &data);
- if (rc) {
- fprintf(stderr, "error: %s: %s\n", cmdname(argv[0]),
- strerror(rc = errno));
- } else {
- printf("%s: object id %Ld, 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;
- int i, count, next_count;
- int verbose;
- int rc = 0;
-
- if (argc != 2 && argc != 3)
- return CMD_HELP;
-
- IOCINIT(data);
- count = strtoul(argv[1], NULL, 0);
-
- if (argc == 3)
- verbose = get_verbose(argv[2]);
- else
- verbose = 1;
-
- data.ioc_obdo1.o_valid = 0xffffffff;
- data.ioc_obdo1.o_id = 2;
- gettimeofday(&start, NULL);
- next_time.tv_sec = start.tv_sec - verbose;
- next_time.tv_usec = start.tv_usec;
- if (verbose != 0)
- printf("%s: getting %d attrs (testing only): %s",
- cmdname(argv[0]), count, ctime(&start.tv_sec));
-
- for (i = 1, next_count = verbose; i <= count; i++) {
- rc = ioctl(fd, OBD_IOC_GETATTR, &data);
- SHMEM_BUMP();
- if (rc < 0) {
- fprintf(stderr, "error: %s: #%d - %s\n",
- cmdname(argv[0]), i, strerror(rc = errno));
- break;
- } else {
- if (be_verbose
- (verbose, &next_time, i, &next_count, count))
- printf("%s: got attr #%d\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: %d 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;
- char *bulk, *b;
- int pages = 1, obdos = 1, count, next_count;
- int verbose = 1, write = 0, rw;
- int i, o, p;
- int len;
- int rc = 0;
-
- if (argc < 2 || argc > 6)
- return CMD_HELP;
-
- count = strtoul(argv[1], NULL, 0);
-
- 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;
-
- verbose = get_verbose(argv[3]);
- }
-
- if (argc >= 5)
- pages = strtoul(argv[4], NULL, 0);
- if (argc >= 6)
- obdos = strtoul(argv[5], NULL, 0);
-
- if (obdos != 1 && obdos != 2) {
- fprintf(stderr, "error: %s: only 1 or 2 obdos supported\n",
- cmdname(argv[0]));
- return -2;
- }
-
- len = pages * PAGE_SIZE;
-
- bulk = calloc(obdos, len);
- if (!bulk) {
- fprintf(stderr, "error: %s: no memory allocating %dx%d pages\n",
- cmdname(argv[0]), obdos, pages);
- return -2;
- }
- IOCINIT(data);
- data.ioc_obdo1.o_id = 2;
- data.ioc_count = len;
- data.ioc_offset = 0;
- data.ioc_plen1 = len;
- data.ioc_pbuf1 = bulk;
- if (obdos > 1) {
- data.ioc_obdo2.o_id = 3;
- data.ioc_plen2 = len;
- data.ioc_pbuf2 = bulk + len;
- }
-
- gettimeofday(&start, NULL);
- next_time.tv_sec = start.tv_sec - verbose;
- next_time.tv_usec = start.tv_usec;
-
- if (verbose != 0)
- printf("%s: %s %d (%dx%d pages) (testing only): %s",
- cmdname(argv[0]), write ? "writing" : "reading",
- count, obdos, pages, ctime(&start.tv_sec));
-
- /*
- * We will put in the start time (and loop count inside the loop)
- * at the beginning of each page so that we will be able to validate
- * (at some later time) whether the data actually made it or not.
- *
- * XXX we do not currently use any of this memory in OBD_IOC_BRW_*
- * just to avoid the overhead of the copy_{to,from}_user. It
- * can be fixed if we ever need to send real data around.
- */
- for (o = 0, b = bulk; o < obdos; o++)
- for (p = 0; p < pages; p++, b += PAGE_SIZE)
- memcpy(b, &start, sizeof(start));
-
- rw = write ? OBD_IOC_BRW_WRITE : OBD_IOC_BRW_READ;
- for (i = 1, next_count = verbose; i <= count; i++) {
- if (write) {
- b = bulk + sizeof(struct timeval);
- for (o = 0; o < obdos; o++)
- for (p = 0; p < pages; p++, b += PAGE_SIZE)
- memcpy(b, &count, sizeof(count));
- }
-
- rc = ioctl(fd, rw, &data);
- 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 %d\n", cmdname(argv[0]),
- write ? "write" : "read", i);
- }
-
- free(bulk);
-
- if (!rc) {
- struct timeval end;
- double diff;
-
- gettimeofday(&end, NULL);
-
- diff = difftime(&end, &start);
-
- --i;
- if (verbose != 0)
- printf("%s: %s %dx%dx%d pages in %.4gs (%.4g pg/s): %s",
- cmdname(argv[0]), write ? "wrote" : "read",
- obdos, pages, i, diff,
- (double)obdos * i * pages / diff,
- ctime(&end.tv_sec));
- }
- return rc;
-}
-
-int jt_obd_lov_config(int argc, char **argv)
-{
- struct obd_ioctl_data data;
- struct lov_desc desc;
- uuid_t *uuidarray;
- int rc, size, i;
- IOCINIT(data);
-
- if (argc <= 6)
- return CMD_HELP;
-
- if (strlen(argv[1]) > sizeof(uuid_t) - 1) {
- fprintf(stderr, "lov_config: no %dB memory for uuid's\n",
- strlen(argv[1]));
- return -ENOMEM;
- }
-
- memset(&desc, 0, sizeof(desc));
- strcpy(desc.ld_uuid, argv[1]);
- desc.ld_default_stripe_count = strtoul(argv[2], NULL, 0);
- desc.ld_default_stripe_size = strtoul(argv[3], NULL, 0);
- desc.ld_default_stripe_offset = (__u64) strtoul(argv[4], NULL, 0);
- desc.ld_pattern = strtoul(argv[5], NULL, 0);
- desc.ld_tgt_count = argc - 6;
-
-
- size = sizeof(uuid_t) * desc.ld_tgt_count;
- uuidarray = malloc(size);
- if (!uuidarray) {
- fprintf(stderr, "lov_config: no %dB memory for uuid's\n", size);
- return -ENOMEM;
- }
- memset(uuidarray, 0, size);
- for (i = 6; i < argc; i++) {
- char *buf = (char *)(uuidarray + i - 6);
- if (strlen(argv[i]) >= sizeof(uuid_t)) {
- fprintf(stderr, "lov_config: arg %d (%s) too long\n",
- i, argv[i]);
- free(uuidarray);
- return -EINVAL;
- }
- strcpy(buf, argv[i]);
- }
-
- data.ioc_inllen1 = sizeof(desc);
- data.ioc_inlbuf1 = (char *)&desc;
- data.ioc_inllen2 = size;
- data.ioc_inlbuf2 = (char *)uuidarray;
-
- if (obd_ioctl_pack(&data, &buf, max)) {
- fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
- return -EINVAL;
- }
-
- rc = ioctl(fd, OBD_IOC_LOV_CONFIG, buf);
- if (rc)
- fprintf(stderr, "lov_config: error: %s: %s\n",
- cmdname(argv[0]), strerror(rc = errno));
- 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) {
- fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
- return 1;
- }
-
- 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;
-
- IOCINIT(data);
-
- if (argc > 2) {
- fprintf(stderr, "usage: %s [numthreads]\n", cmdname(argv[0]));
- return 1;
- } else if (argc == 2) {
- data.ioc_inllen1 = strlen(argv[1]) + 1;
- data.ioc_inlbuf1 = argv[1];
- } else {
- data.ioc_inllen1 = 0;
- }
-
- if (obd_ioctl_pack(&data, &buf, max)) {
- fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
- return -2;
- }
-
- 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) {
- fprintf(stderr, "usage: %s\n", cmdname(argv[0]));
- return 1;
- }
-
- 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_newconn(int argc, char **argv)
-{
- int rc;
- struct obd_ioctl_data data;
-
- IOCINIT(data);
- if (argc != 1)
- return CMD_HELP;
-
- rc = ioctl(fd, OBD_IOC_RECOVD_NEWCONN, &data);
- 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 */
- {"lovconfig", jt_obd_lov_config, 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>"},
- {"getattr", jt_obd_getattr, 0, "getattr <id>"},
- {"setattr", jt_obd_setattr, 0, "setattr <id> <mode>"},
- {"newconn", jt_obd_newconn, 0, "newconn [newuuid]"},
- {"test_getattr", jt_obd_test_getattr, 0, "test_getattr <count> [verbose]"},
- {"test_brw", jt_obd_test_brw, 0, "test_brw <count> [write [verbose]]"},
- {"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_config(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_newconn(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 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;
-}
-
-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\" ", cmd->pc_name);
- printf("\nas 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;
- 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)
- done = 1;
-
- free(line);
- }
- 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_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