N: Geert Uytterhoeven
E: geert@linux-m68k.org
-W: http://www.cs.kuleuven.ac.be/~geert/
+W: http://home.tvd.be/cr26864/
P: 1024/EC4A1EE1 8B 88 38 35 88 1E 95 A1 CD 9E AE DC 4B 4A 2F 41
D: m68k/Amiga and PPC/CHRP Longtrail coordinator
D: Frame buffer device and XF68_FBDev maintainer
<legalnotice>
<para>
- This documentation 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.
- </para>
-
- <para>
- 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.
- </para>
-
- <para>
- 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
- </para>
-
- <para>
- For more details see the file COPYING in the source
- distribution of Linux.
+ 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 no Invariant Sections, with no Front-Cover Texts,
+ and with no Back-Cover Texts. A copy of the license is included
+ in the section entitled "GNU Free Documentation License".
</para>
</legalnotice>
</bookinfo>
</chapter>
- <appendix>
+ <appendix id="api">
<title>
- API reference
+ Linux parallel port driver API reference
</title>
!Fdrivers/parport/daisy.c parport_device_num
removed.
</para>
</appendix>
+
+ <appendix id="fdl">
+ <title>
+ GNU Free Documentation License
+ </title>
+
+ <literallayout class="monospaced">
+ 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.
+ </literallayout>
+ </appendix>
+
</book>
<!-- Local Variables: -->
<!-- sgml-indent-step: 1 -->
<!-- sgml-indent-data: 1 -->
<!-- End: -->
-
The latest version of fbset can be found at
- http://www.cs.kuleuven.ac.be/~geert/bin/
+ http://home.tvd.be/cr26864/Linux/fbdev/
10. Credits
--- /dev/null
+ The text below describes the locking rules for VFS-related methods.
+It is (believed to be) up-to-date. *Please*, if you change anything in
+prototypes or locking protocols - update this file. And update the relevant
+instances in the tree, don't leave that to maintainers of filesystems/devices/
+etc. At the very least, put the list of dubious cases in the end of this file.
+Don't turn it into log - maintainers of out-of-the-tree code are supposed to
+be able to use diff(1).
+ Thing currently missing here: socket operations. Alexey?
+
+--------------------------- dentry_operations --------------------------
+prototypes:
+ int (*d_revalidate)(struct dentry *, int);
+ 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 *);
+
+locking rules:
+ none have BKL
+ dcache_lock may block
+d_revalidate: no yes
+d_hash no yes
+d_compare: yes no
+d_delete: yes no
+d_release: no yes
+d_iput: no yes
+
+--------------------------- inode_operations ---------------------------
+prototypes:
+ int (*create) (struct inode *,struct dentry *,int);
+ struct dentry * (*lookup) (struct inode *,struct dentry *);
+ int (*link) (struct dentry *,struct inode *,struct dentry *);
+ int (*unlink) (struct inode *,struct dentry *);
+ int (*symlink) (struct inode *,struct dentry *,const char *);
+ int (*mkdir) (struct inode *,struct dentry *,int);
+ int (*rmdir) (struct inode *,struct dentry *);
+ int (*mknod) (struct inode *,struct dentry *,int,int);
+ int (*rename) (struct inode *, struct dentry *,
+ struct inode *, struct dentry *);
+ int (*readlink) (struct dentry *, char *,int);
+ int (*follow_link) (struct dentry *, struct nameidata *);
+ void (*truncate) (struct inode *);
+ int (*permission) (struct inode *, int);
+ int (*revalidate) (struct dentry *);
+ int (*setattr) (struct dentry *, struct iattr *);
+ int (*getattr) (struct dentry *, struct iattr *);
+
+locking rules:
+ all may block
+ BKL i_sem(inode) i_zombie(inode)
+lookup: yes yes no
+create: yes yes yes
+link: yes yes yes
+mknod: yes yes yes
+mkdir: yes yes yes
+unlink: yes yes yes
+rmdir: yes yes yes (see below)
+rename: yes yes (both) yes (both) (see below)
+readlink: no no no
+follow_link: no no no
+truncate: yes yes no (see below)
+setattr: yes if ATTR_SIZE no
+permssion: yes no no
+getattr: (see below)
+revalidate: no (see below)
+ Additionally, ->rmdir() has i_zombie on victim and so does ->rename()
+in case when target exists and is a directory.
+ ->revalidate(), it may be called both with and without the i_sem
+on dentry->d_inode. VFS never calls it with i_zombie on dentry->d_inode,
+but watch for other methods directly calling this one...
+ ->truncate() is never called directly - it's a callback, not a
+method. It's called by vmtruncate() - library function normally used by
+->setattr(). Locking information above applies to that call (i.e. is
+inherited from ->setattr() - vmtruncate() is used when ATTR_SIZE had been
+passed).
+ ->getattr() is currently unused.
+
+--------------------------- super_operations ---------------------------
+prototypes:
+ void (*read_inode) (struct inode *);
+ void (*write_inode) (struct inode *, int);
+ void (*put_inode) (struct inode *);
+ void (*delete_inode) (struct inode *);
+ void (*put_super) (struct super_block *);
+ void (*write_super) (struct super_block *);
+ int (*statfs) (struct super_block *, struct statfs *);
+ int (*remount_fs) (struct super_block *, int *, char *);
+ void (*clear_inode) (struct inode *);
+ void (*umount_begin) (struct super_block *);
+
+locking rules:
+ All may block.
+ BKL s_lock mount_sem
+read_inode: yes (see below)
+write_inode: no
+put_inode: no
+delete_inode: no
+clear_inode: no
+put_super: yes yes maybe (see below)
+write_super: yes yes maybe (see below)
+statfs: yes no no
+remount_fs: yes yes maybe (see below)
+umount_begin: yes no maybe (see below)
+
+->read_inode() is not a method - it's a callback used in iget()/iget4().
+rules for mount_sem are not too nice - it is going to die and be replaced
+by better scheme anyway.
+
+--------------------------- file_system_type ---------------------------
+prototypes:
+ struct super_block *(*read_super) (struct super_block *, void *, int);
+locking rules:
+may block BKL ->s_lock mount_sem
+yes yes yes maybe
+
+--------------------------- address_space_operations --------------------------
+prototypes:
+ int (*writepage)(struct file *, struct page *);
+ int (*readpage)(struct file *, struct page *);
+ int (*sync_page)(struct page *);
+ int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
+ int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
+ int (*bmap)(struct address_space *, long);
+locking rules:
+ All may block
+ BKL PageLocked(page)
+writepage: no yes
+readpage: no yes
+sync_page: no maybe
+prepare_write: no yes
+commit_write: no yes
+bmap: yes
+
+ ->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
+may be called from the request handler (/dev/loop).
+ ->sync_page() locking rules are not well-defined - usually it is called
+with lock on page, but that is not guaranteed. Considering the currently
+existsing instances of this method ->sync_page() itself doesn't look
+well-defined...
+ ->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some
+filesystems and by the swapper. The latter will eventually go away. All
+instances do not actually need the BKL. Please, keep it that way and don't
+breed new callers.
+ Note: currently almost all instances of address_space methods are
+using BKL for internal serialization and that's one of the worst sources
+of contention. Normally they are calling library functions (in fs/buffer.c)
+and pass foo_get_block() as a callback (on local block-based filesystems,
+indeed). BKL is not needed for library stuff and is usually taken by
+foo_get_block(). It's an overkill, since block bitmaps can be protected by
+internal fs locking and real critical areas are much smaller than the areas
+filesystems protect now.
+
+--------------------------- file_lock ------------------------------------
+prototypes:
+ void (*fl_notify)(struct file_lock *); /* unblock callback */
+ void (*fl_insert)(struct file_lock *); /* lock insertion callback */
+ void (*fl_remove)(struct file_lock *); /* lock removal callback */
+
+locking rules:
+ BKL may block
+fl_notify: yes no
+fl_insert: yes maybe
+fl_remove: yes maybe
+ Currently only NLM provides instances of this class. None of the
+them block. If you have out-of-tree instances - please, show up. Locking
+in that area will change.
+
+--------------------------- buffer_head -----------------------------------
+prototypes:
+ void (*b_end_io)(struct buffer_head *bh, int uptodate);
+
+locking rules:
+ called from interrupts. In other words, extreme care is needed here.
+bh is locked, but that's all warranties we have here. Currently only RAID1,
+highmem and fs/buffer.c are providing these. Block devices call this method
+upon the IO completion.
+
+--------------------------- block_device_operations -----------------------
+prototypes:
+ int (*open) (struct inode *, struct file *);
+ int (*release) (struct inode *, struct file *);
+ int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
+ int (*check_media_change) (kdev_t);
+ int (*revalidate) (kdev_t);
+locking rules:
+ BKL bd_sem
+open: yes yes
+release: yes yes
+ioctl: yes no
+check_media_change: yes no
+revalidate: yes no
+
+The last two are called only from check_disk_change(). Prototypes are very
+bad - as soon as we'll get disk_struct they will change (and methods will
+become per-disk instead of per-partition).
+
+--------------------------- file_operations -------------------------------
+prototypes:
+ loff_t (*llseek) (struct file *, loff_t, int);
+ ssize_t (*read) (struct file *, char *, size_t, loff_t *);
+ ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
+ int (*readdir) (struct file *, void *, filldir_t);
+ unsigned int (*poll) (struct file *, struct poll_table_struct *);
+ int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
+ int (*mmap) (struct file *, struct vm_area_struct *);
+ int (*open) (struct inode *, struct file *);
+ int (*flush) (struct file *);
+ int (*release) (struct inode *, struct file *);
+ int (*fsync) (struct file *, struct dentry *, int datasync);
+ int (*fasync) (int, struct file *, int);
+ int (*lock) (struct file *, int, struct file_lock *);
+ ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
+ ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
+};
+
+locking rules:
+ All except ->poll() may block.
+ BKL
+llseek: yes
+read: no
+write: no
+readdir: yes (see below)
+poll: no
+ioctl: yes (see below)
+mmap: no
+open: maybe (see below)
+flush: yes
+release: yes
+fsync: yes (see below)
+fasync: yes (see below)
+lock: yes
+readv: no
+writev: no
+
+->open() locking is in-transit: big lock partially moved into the methods.
+The only exception is ->open() in the instances of file_operations that never
+end up in ->i_fop/->proc_fops, i.e. ones that belong to character devices
+(chrdev_open() takes lock before replacing ->f_op and calling the secondary
+method. As soon as we fix the handling of module reference counters all
+instances of ->open() will be called without the BKL. At the same point
+->release() will lose BKL. Currently ext2_release() is *the* source of
+contention on fs-intensive loads and dropping BKL on ->release() will get
+rid of that (we will still need some locking for cases when we close a file
+that had been opened r/w, but that can be done using the internal locking with
+smaller critical areas). sock_close() is also going to win from that change.
+
+->fasync() is a mess. This area needs a big cleanup and that will probably
+affect locking.
+
+->readdir() and ->ioctl() on directories must be changed. Ideally we would
+move ->readdir() to inode_operations and use a separate method for directory
+->ioctl() or kill the latter completely. One of the problems is that for
+anything that resembles union-mount we won't have a struct file for all
+components. And there are other reasons why the current interface is a mess...
+
+->read on directories probably must go away - we should just enforce -EISDIR
+in sys_read() and friends.
+
+->fsync() has i_sem on inode.
+
+--------------------------- dquot_operations -------------------------------
+prototypes:
+ void (*initialize) (struct inode *, short);
+ void (*drop) (struct inode *);
+ int (*alloc_block) (const struct inode *, unsigned long, char);
+ int (*alloc_inode) (const struct inode *, unsigned long);
+ void (*free_block) (const struct inode *, unsigned long);
+ void (*free_inode) (const struct inode *, unsigned long);
+ int (*transfer) (struct dentry *, struct iattr *);
+
+locking rules:
+ BKL
+initialize: no
+drop: no
+alloc_block: yes
+alloc_inode: yes
+free_block: yes
+free_inode: yes
+transfer: no
+
+--------------------------- vm_operations_struct -----------------------------
+prototypes:
+ void (*open)(struct vm_area_struct*);
+ void (*close)(struct vm_area_struct*);
+ void (*unmap)(struct vm_area_struct*, unsigned long, size_t);
+ void (*protect)(struct vm_area_struct*, unsigned long, size_t, unsigned);
+ int (*sync)(struct vm_area_struct*, unsigned long, size_t, unsigned);
+ struct page *(*nopage)(struct vm_area_struct*, unsigned long, int);
+ struct page *(*wppage)(struct vm_area_struct*, unsigned long, struct page*);
+ int (*swapout)(struct page *, struct file *);
+
+locking rules:
+ BKL mmap_sem
+open: no yes
+close: no yes
+sync: no yes
+unmap: no yes
+nopage: no yes
+swapout: yes yes
+wpppage: (see below)
+protect: (see below)
+
+->wppage() and ->protect() have no instances and nothing calls them; looks like
+they must die...
+
+================================================================================
+ Dubious stuff
+
+(if you break something or notice that it is broken and do not fix it yourself
+- at least put it here)
+
+ipc/shm.c::shm_delete() - may need BKL.
+->read() and ->write() in many drivers are (probably) missing BKL.
+drivers/sgi/char/graphics.c::sgi_graphics_nopage() - may need BKL.
int error;
char * filename;
- lock_kernel();
filename = getname(filenamei);
error = PTR_ERR(filename);
if (IS_ERR(filename))
error = do_execve(filename, argv, envp, regs);
putname(filename);
out:
- unlock_kernel();
return error;
}
buf.count = count;
buf.error = 0;
- lock_kernel();
error = vfs_readdir(file, filldir32, &buf);
if (error < 0)
goto out_putf;
}
out_putf:
- unlock_kernel();
fput(file);
out:
return error;
buf.count = 0;
buf.dirent = dirent;
- lock_kernel();
error = vfs_readdir(file, fillonedir32, &buf);
if (error >= 0)
error = buf.count;
- unlock_kernel();
-
fput(file);
out:
return error;
struct file *file;
long ret = -EBADF;
- lock_kernel();
file = fget(fd);
if(!file)
goto bad_file;
out:
fput(file);
bad_file:
- unlock_kernel();
return ret;
}
struct file *file;
int ret = -EBADF;
- lock_kernel();
file = fget(fd);
if(!file)
goto bad_file;
out:
fput(file);
bad_file:
- unlock_kernel();
return ret;
}
{
int version, err;
- lock_kernel();
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
break;
}
- unlock_kernel();
return err;
}
}
kern_msg.msg_flags = user_flags;
- lock_kernel();
sock = sockfd_lookup(fd, &err);
if (sock != NULL) {
if (sock->file->f_flags & O_NONBLOCK)
err = sock_sendmsg(sock, &kern_msg, total_len);
sockfd_put(sock);
}
- unlock_kernel();
/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
if(ctl_buf != ctl)
cmsg_ptr = (unsigned long) kern_msg.msg_control;
kern_msg.msg_flags = 0;
- lock_kernel();
sock = sockfd_lookup(fd, &err);
if (sock != NULL) {
struct scm_cookie scm;
if (sock->file->f_flags & O_NONBLOCK)
user_flags |= MSG_DONTWAIT;
memset(&scm, 0, sizeof(scm));
+ lock_kernel();
err = sock->ops->recvmsg(sock, &kern_msg, total_len,
user_flags, &scm);
if(err >= 0) {
scm_detach_fds32(&kern_msg, &scm);
}
}
+ unlock_kernel();
sockfd_put(sock);
}
- unlock_kernel();
if(uaddr != NULL && err >= 0)
err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr,
sys32_personality(unsigned long personality)
{
int ret;
- lock_kernel();
if (current->personality == PER_LINUX32 && personality == PER_LINUX)
personality = PER_LINUX32;
ret = sys_personality(personality);
- unlock_kernel();
if (ret == PER_LINUX32)
ret = PER_LINUX;
return ret;
asmlinkage long
sys_iopl (int level, long arg1, long arg2, long arg3)
{
- lock_kernel();
printk(KERN_ERR "sys_iopl(level=%d)!\n", level);
- unlock_kernel();
return -ENOSYS;
}
asmlinkage long
sys_vm86 (long arg0, long arg1, long arg2, long arg3)
{
- lock_kernel();
printk(KERN_ERR "sys_vm86(%lx, %lx, %lx, %lx)!\n", arg0, arg1, arg2, arg3);
- unlock_kernel();
return -ENOSYS;
}
asmlinkage long
sys_modify_ldt (long arg0, long arg1, long arg2, long arg3)
{
- lock_kernel();
printk(KERN_ERR "sys_modify_ldt(%lx, %lx, %lx, %lx)!\n", arg0, arg1, arg2, arg3);
- unlock_kernel();
return -ENOSYS;
}
struct nameidata nd;
int error;
- lock_kernel();
error = user_path_walk(filename, &nd);
if (!error) {
error = do_revalidate(nd.dentry);
error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
path_release(&nd);
}
- unlock_kernel();
return error;
}
struct nameidata nd;
int error;
- lock_kernel();
error = user_path_walk_link(filename, &nd);
if (!error) {
error = do_revalidate(nd.dentry);
error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
path_release(&nd);
}
- unlock_kernel();
return error;
}
struct file * f;
int err = -EBADF;
- lock_kernel();
f = fget(fd);
if (f) {
struct dentry * dentry = f->f_dentry;
err = cp_ia64_old_stat(dentry->d_inode, statbuf);
fput(f);
}
- unlock_kernel();
return err;
}
/*
** linux/amiga/chipram.c
**
-** Modified 03-May-94 by Geert Uytterhoeven
-** (Geert.Uytterhoeven@cs.kuleuven.ac.be)
+** Modified 03-May-94 by Geert Uytterhoeven <geert@linux-m68k.org>
** - 64-bit aligned allocations for full AGA compatibility
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/zorro.h>
#include <asm/amigahw.h>
struct chip_desc {
u_long amiga_chip_size;
static unsigned long chipavail;
+static struct resource chipram = { "Chip RAM", 0 };
+
unsigned long amiga_chip_avail( void )
{
#ifdef DEBUG
}
-__init
-void amiga_chip_init (void)
+void __init amiga_chip_init (void)
{
struct chip_desc *dp;
*/
amiga_chip_size -= 0x4000;
#endif
+ chipram.end = amiga_chip_size-1;
+ request_resource(&iomem_resource, &chipram);
/* initialize start boundary */
#endif
}
-void *amiga_chip_alloc (long size)
+void *amiga_chip_alloc(long size, const char *name)
{
/* last chunk */
struct chip_desc *dp;
size = (size + 7) & ~7;
#ifdef DEBUG
- printk("chip_alloc: allocate %ld bytes\n", size);
+ printk("amiga_chip_alloc: allocate %ld bytes\n", size);
#endif
/*
dp = DP((unsigned long)ptr + dp->length);
dp->alloced = 1;
#ifdef DEBUG
- printk ("chip_alloc: no split\n");
+ printk ("amiga_chip_alloc: no split\n");
#endif
} else {
/* split the extent; use the end part */
long newsize = dp->length - (2*sizeof(*dp) + size);
#ifdef DEBUG
- printk ("chip_alloc: splitting %d to %ld\n", dp->length,
+ printk ("amiga_chip_alloc: splitting %d to %ld\n", dp->length,
newsize);
#endif
dp->length = newsize;
}
#ifdef DEBUG
- printk ("chip_alloc: returning %p\n", ptr);
+ printk ("amiga_chip_alloc: returning %p\n", ptr);
#endif
if ((unsigned long)ptr & 7)
- panic("chip_alloc: alignment violation\n");
+ panic("amiga_chip_alloc: alignment violation\n");
chipavail -= size + (2*sizeof(*dp)); /*MILAN*/
+ if (!request_mem_region(ZTWO_PADDR(ptr), size, name))
+ printk(KERN_WARNING "amiga_chip_alloc: region of size %ld at 0x%08lx "
+ "is busy\n", size, ZTWO_PADDR(ptr));
+
return ptr;
}
#endif
/* deallocate the chunk */
sdp->alloced = edp->alloced = 0;
+ release_mem_region(ZTWO_PADDR(ptr), sdp->length);
/* check if we should merge with the previous chunk */
if (!sdp->first && !sdp[-1].alloced) {
int sys_iopl(int a1, int a2, int a3, int a4)
{
- lock_kernel();
printk(KERN_ERR "sys_iopl(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
- unlock_kernel();
return (-ENOSYS);
}
int sys_vm86(int a1, int a2, int a3, int a4)
{
- lock_kernel();
printk(KERN_ERR "sys_vm86(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
- unlock_kernel();
return (-ENOSYS);
}
int sys_modify_ldt(int a1, int a2, int a3, int a4)
{
- lock_kernel();
printk(KERN_ERR "sys_modify_ldt(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
- unlock_kernel();
return (-ENOSYS);
}
{
int version, ret;
- lock_kernel();
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
break;
}
- unlock_kernel();
return ret;
}
{
int version, err;
- lock_kernel();
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
else
err = -EINVAL;
out:
- unlock_kernel();
return err;
}
{
int ret;
- lock_kernel();
switch(name) {
case _PCONF_LINK:
ret = LINK_MAX;
ret = -EINVAL;
break;
}
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = sunos_fpathconf(0, name); /* XXX cheese XXX */
- unlock_kernel();
return ret;
}
int ret;
/* SunOS binaries expect that select won't change the tvp contents */
- lock_kernel();
ret = sys_select (width, inp, outp, exp, tvp);
if (ret == -EINTR && tvp) {
time_t sec, usec;
if (sec == 0 && usec == 0)
ret = 0;
}
- unlock_kernel();
return ret;
}
int ret;
/* So stupid... */
- lock_kernel();
if((!pid || pid == current->pid) &&
!pgid) {
sys_setsid();
} else {
ret = sys_setpgid(pid, pgid);
}
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = sys_wait4((pid ? pid : -1), stat_addr, options, ru);
- unlock_kernel();
return ret;
}
{
long ret;
- lock_kernel();
switch (name){
case _SC_ARG_MAX:
ret = ARG_MAX;
ret = -1;
break;
};
- unlock_kernel();
return ret;
}
union semun arg4;
int ret;
- lock_kernel();
switch (op) {
case 0:
/* Most arguments match on a 1:1 basis but cmd doesn't */
ret = -EINVAL;
break;
};
- unlock_kernel();
return ret;
}
unsigned long arg5;
int rval;
- lock_kernel();
switch(op) {
case 0:
rval = sys_msgget((key_t)arg1, (int)arg2);
(struct msqid_ds *)arg3);
break;
case 2:
+ lock_kernel();
sp = (struct sparc_stackf *)current->thread.kregs->u_regs[UREG_FP];
arg5 = sp->xxargs[0];
+ unlock_kernel();
rval = sys_msgrcv((int)arg1, (struct msgbuf *)arg2,
(size_t)arg3, (long)arg4, (int)arg5);
break;
rval = -EINVAL;
break;
}
- unlock_kernel();
return rval;
}
unsigned long raddr;
int rval;
- lock_kernel();
switch(op) {
case 0:
/* sys_shmat(): attach a shared memory area */
rval = -EINVAL;
break;
};
- unlock_kernel();
return rval;
}
static inline int check_nonblock(int ret, int fd)
{
if (ret == -EAGAIN) {
- struct file * file = fcheck(fd);
- if (file && (file->f_flags & O_NDELAY))
- ret = -SUNOS_EWOULDBLOCK;
+ struct file * file = fget(fd);
+ if (file) {
+ if (file->f_flags & O_NDELAY)
+ ret = -SUNOS_EWOULDBLOCK;
+ fput(file);
+ }
}
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys_read(fd,buf,count),fd);
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys_readv(fd,vector,count),fd);
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys_write(fd,buf,count),fd);
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys_writev(fd,vector,count),fd);
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys_recv(fd,ubuf,size,flags),fd);
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys_send(fd,buff,len,flags),fd);
- unlock_kernel();
return ret;
}
{
int ret, one = 1;
- lock_kernel();
ret = sys_socket(family, type, protocol);
if (ret < 0)
goto out;
sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
(char *)&one, sizeof(one));
out:
- unlock_kernel();
return ret;
}
{
int ret, one = 1;
- lock_kernel();
while (1) {
ret = check_nonblock(sys_accept(fd,sa,addrlen),fd);
if (ret != -ENETUNREACH && ret != -EHOSTUNREACH)
sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
(char *)&one, sizeof(one));
out:
- unlock_kernel();
return ret;
}
int tr_opt = optname;
int ret;
- lock_kernel();
if (level == SOL_IP) {
/* Multicast socketopts (ttl, membership) */
if (tr_opt >=2 && tr_opt <= 6)
tr_opt += 30;
}
ret = sys_setsockopt(fd, level, tr_opt, optval, optlen);
- unlock_kernel();
return ret;
}
int tr_opt = optname;
int ret;
- lock_kernel();
if (level == SOL_IP) {
/* Multicast socketopts (ttl, membership) */
if (tr_opt >=2 && tr_opt <= 6)
tr_opt += 30;
}
ret = sys_getsockopt(fd, level, tr_opt, optval, optlen);
- unlock_kernel();
return ret;
}
{
int err;
- lock_kernel();
/* No need for backward compatibility. We can start fresh... */
if (call <= SEMCTL)
else
err = -EINVAL;
out:
- unlock_kernel();
return err;
}
asmlinkage int sparc64_personality(unsigned long personality)
{
int ret;
- lock_kernel();
if (current->personality == PER_LINUX32 && personality == PER_LINUX)
personality = PER_LINUX32;
ret = sys_personality(personality);
- unlock_kernel();
if (ret == PER_LINUX32)
ret = PER_LINUX;
return ret;
struct file *file;
long ret = -EBADF;
- lock_kernel();
-
file = fget(fd);
if(!file)
goto bad_file;
fput(file);
bad_file:
- unlock_kernel();
return ret;
}
struct file *file;
int ret = -EBADF;
- lock_kernel();
-
file = fget(fd);
if(!file)
goto bad_file;
fput(file);
bad_file:
- unlock_kernel();
return ret;
}
if (!IS_ERR(tmp)) {
fd = get_unused_fd();
if (fd >= 0) {
- struct file * f;
- lock_kernel();
- f = filp_open(tmp, flags, mode);
- unlock_kernel();
+ struct file * f = filp_open(tmp, flags, mode);
error = PTR_ERR(f);
if (IS_ERR(f))
goto out_error;
{
int ret;
- lock_kernel();
switch(name) {
case _PCONF_LINK:
ret = LINK_MAX;
ret = -EINVAL;
break;
}
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = sunos_fpathconf(0, name); /* XXX cheese XXX */
- unlock_kernel();
return ret;
}
int ret;
/* SunOS binaries expect that select won't change the tvp contents */
- lock_kernel();
ret = sys32_select (width, inp, outp, exp, tvp_x);
if (ret == -EINTR && tvp_x) {
struct timeval32 *tvp = (struct timeval32 *)A(tvp_x);
if (sec == 0 && usec == 0)
ret = 0;
}
- unlock_kernel();
return ret;
}
int ret;
/* So stupid... */
- lock_kernel();
if((!pid || pid == current->pid) &&
!pgid) {
sys_setsid();
} else {
ret = sys_setpgid(pid, pgid);
}
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = sys32_wait4((pid ? pid : ((__kernel_pid_t32)-1)),
stat_addr, options, ru);
- unlock_kernel();
return ret;
}
asmlinkage int sunos_audit(void)
{
- lock_kernel();
printk ("sys_audit\n");
- unlock_kernel();
return -1;
}
{
s32 ret;
- lock_kernel();
switch (name){
case _SC_ARG_MAX:
ret = ARG_MAX;
ret = -1;
break;
};
- unlock_kernel();
return ret;
}
union semun arg4;
int ret;
- lock_kernel();
switch (op) {
case 0:
/* Most arguments match on a 1:1 basis but cmd doesn't */
ret = -EINVAL;
break;
};
- unlock_kernel();
return ret;
}
u32 arg5;
int rval;
- lock_kernel();
switch(op) {
case 0:
rval = sys_msgget((key_t)arg1, (int)arg2);
rval = -EINVAL;
break;
}
- unlock_kernel();
return rval;
}
mm_segment_t old_fs = get_fs();
int rval;
- lock_kernel();
switch(op) {
case 0:
/* sys_shmat(): attach a shared memory area */
rval = -EINVAL;
break;
};
- unlock_kernel();
return rval;
}
static inline int check_nonblock(int ret, int fd)
{
if (ret == -EAGAIN) {
- struct file * file = fcheck(fd);
- if (file && (file->f_flags & O_NDELAY))
- ret = -SUNOS_EWOULDBLOCK;
+ struct file * file = fget(fd);
+ if (file) {
+ if (file->f_flags & O_NDELAY)
+ ret = -SUNOS_EWOULDBLOCK;
+ fput(file);
+ }
}
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys_read(fd, (char *)A(buf), count), fd);
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys32_readv(fd, vector, count), fd);
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys_write(fd, (char *)A(buf), count), fd);
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys32_writev(fd, vector, count), fd);
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys_recv(fd, (void *)A(ubuf), size, flags), fd);
- unlock_kernel();
return ret;
}
{
int ret;
- lock_kernel();
ret = check_nonblock(sys_send(fd, (void *)A(buff), len, flags), fd);
- unlock_kernel();
return ret;
}
{
int ret, one = 1;
- lock_kernel();
ret = sys_socket(family, type, protocol);
if (ret < 0)
goto out;
sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
(char *)&one, sizeof(one));
out:
- unlock_kernel();
return ret;
}
{
int ret, one = 1;
- lock_kernel();
while (1) {
ret = check_nonblock(sys_accept(fd, (struct sockaddr *)A(sa),
(int *)A(addrlen)), fd);
sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT,
(char *)&one, sizeof(one));
out:
- unlock_kernel();
return ret;
}
int tr_opt = optname;
int ret;
- lock_kernel();
if (level == SOL_IP) {
/* Multicast socketopts (ttl, membership) */
if (tr_opt >=2 && tr_opt <= 6)
tr_opt += 30;
}
ret = sys_setsockopt(fd, level, tr_opt, (char *)A(optval), optlen);
- unlock_kernel();
return ret;
}
int tr_opt = optname;
int ret;
- lock_kernel();
if (level == SOL_IP) {
/* Multicast socketopts (ttl, membership) */
if (tr_opt >=2 && tr_opt <= 6)
tr_opt += 30;
}
ret = sys32_getsockopt(fd, level, tr_opt, optval, optlen);
- unlock_kernel();
return ret;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,48))
proc_entry->proc_fops = &i2cproc_operations;
+ proc_entry->owner = THIS_MODULE;
#else
proc_entry->ops = &i2cproc_inode_operations;
#endif
#include <linux/module.h>
#include <linux/version.h>
#include <linux/poll.h>
+#include <linux/smp_lock.h>
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
#else
{
int flags;
- MOD_INC_USE_COUNT;
+ lock_kernel();
save_flags(flags);
cli();
if_used++;
(struct divert_info **) filep->private_data = &divert_info_head;
restore_flags(flags);
/* start_divert(); */
+ unlock_kernel();
return (0);
} /* isdn_divert_open */
divert_info_head = divert_info_head->next;
kfree(inf);
}
- MOD_DEC_USE_COUNT;
return (0);
} /* isdn_divert_close */
return (-1);
}
isdn_divert_entry->proc_fops = &isdn_fops;
+ isdn_divert_entry->owner = THIS_MODULE;
#endif /* CONFIG_PROC_FS */
return (0);
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/pci.h>
+#include <linux/smp_lock.h>
#include "hysdn_defs.h"
struct conf_writedata *cnf;
char *cp, *tmp;
- MOD_INC_USE_COUNT; /* lock module */
-
/* now search the addressed card */
+ lock_kernel();
card = card_root;
while (card) {
pd = card->procconf;
card = card->next; /* search next entry */
}
if (!card) {
- MOD_DEC_USE_COUNT; /* unlock module */
+ unlock_kernel();
return (-ENODEV); /* device is unknown/invalid */
}
if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
/* write only access -> write boot file or conf line */
if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) {
- MOD_DEC_USE_COUNT;
+ unlock_kernel();
return (-EFAULT);
}
cnf->card = card;
/* read access -> output card info data */
if (!(tmp = (char *) kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
- MOD_DEC_USE_COUNT;
+ unlock_kernel();
return (-EFAULT); /* out of memory */
}
filep->private_data = tmp; /* start of string */
*cp++ = '\n';
*cp = 0; /* end of string */
} else { /* simultaneous read/write access forbidden ! */
- MOD_DEC_USE_COUNT; /* unlock module */
+ unlock_kernel();
return (-EPERM); /* no permission this time */
}
+ unlock_kernel();
return (0);
} /* hysdn_conf_open */
if (filep->private_data)
kfree(filep->private_data); /* release memory */
}
- MOD_DEC_USE_COUNT; /* reduce usage count */
return (retval);
} /* hysdn_conf_close */
S_IFREG | S_IRUGO | S_IWUSR,
hysdn_proc_entry)) != NULL) {
((struct proc_dir_entry *) card->procconf)->proc_fops = &conf_fops;
+ ((struct proc_dir_entry *) card->procconf)->owner = THIS_MODULE;
hysdn_proclog_init(card); /* init the log file entry */
}
card = card->next; /* next entry */
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/pci.h>
+#include <linux/smp_lock.h>
#include "hysdn_defs.h"
struct procdata *pd;
ulong flags;
- MOD_INC_USE_COUNT; /* lock module */
+ lock_kernel();
card = card_root;
while (card) {
pd = card->procfs;
card = card->next; /* search next entry */
}
if (!card) {
- MOD_DEC_USE_COUNT; /* unlock module */
+ unlock_kernel();
return (-ENODEV); /* device is unknown/invalid */
}
filep->private_data = card; /* remember our own card */
if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
/* write only access -> boot pof data */
if (pof_boot_open(card)) {
- MOD_DEC_USE_COUNT; /* unlock module */
+ unlock_kernel();
return (-EPERM); /* no permission this time */
}
} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
restore_flags(flags);
} else { /* simultaneous read/write access forbidden ! */
- MOD_DEC_USE_COUNT; /* unlock module */
+ unlock_kernel();
return (-EPERM); /* no permission this time */
}
+ unlock_kernel();
return (0);
} /* hysdn_log_open */
}
} /* read access */
- MOD_DEC_USE_COUNT;
return (retval);
} /* hysdn_log_close */
memset(pd, 0, sizeof(struct procdata));
sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
- if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL)
+ if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
pd->log->proc_fops = &log_fops; /* set new operations table */
+ pd->log->owner = THIS_MODULE;
+ }
init_waitqueue_head(&(pd->rd_queue));
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/pci.h>
+#include <linux/smp_lock.h>
#include "hysdn_defs.h"
struct procdata *pd;
ulong flags;
- MOD_INC_USE_COUNT; /* lock module */
+ lock_kernel();
card = card_root;
while (card) {
pd = card->proclog;
card = card->next; /* search next entry */
}
if (!card) {
- MOD_DEC_USE_COUNT; /* unlock module */
+ unlock_kernel();
return (-ENODEV); /* device is unknown/invalid */
}
filep->private_data = card; /* remember our own card */
(struct log_data **) filep->private_data = &(pd->log_head);
restore_flags(flags);
} else { /* simultaneous read/write access forbidden ! */
- MOD_DEC_USE_COUNT; /* unlock module */
+ unlock_kernel();
return (-EPERM); /* no permission this time */
}
+ unlock_kernel();
return (0);
} /* hysdn_log_open */
}
} /* read access */
- MOD_DEC_USE_COUNT;
return (retval);
} /* hysdn_log_close */
if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
memset(pd, 0, sizeof(struct procdata));
sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
- if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL)
+ if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
pd->log->proc_fops = &log_fops;
+ pd->log->owner = THIS_MODULE;
+ }
init_waitqueue_head(&(pd->rd_queue));
}
#if LINUX_VERSION_CODE < 0x20326
static struct file_operations nftl_fops = {
- NULL, /* lseek - default */
- block_read, /* read - block dev read */
- block_write, /* write - block dev write */
- NULL, /* readdir - not here! */
- NULL, /* select */
- nftl_ioctl, /* ioctl */
- NULL, /* mmap */
- nftl_open, /* open */
- NULL, /* flush */
- nftl_release, /* no special release code... */
- block_fsync /* fsync */
+ read: block_read,
+ write: block_write,
+ ioctl: nftl_ioctl,
+ open: nftl_open,
+ release: nftl_release,
+ fsync: block_fsync,
};
#else
static struct block_device_operations nftl_fops =
for (i = 0; pci_clone_list[i].vendor != 0; i++) {
struct pci_dev *pdev = NULL;
- unsigned int pci_ioaddr;
+ unsigned int pci_ioaddr = 0;
while ((pdev = pci_find_device(pci_clone_list[i].vendor, pci_clone_list[i].dev_id, pdev))) {
if (pci_enable_device(pdev))
* 13-03-1999: Get DeviceID from non-IEEE 1284.3 devices too.
* 22-02-2000: Count devices that are actually detected.
*
+ * The block comments above the functions in this file are
+ * licensed as part of the generated file
+ * Documentation/DocBook/parportbook.sgml under the GNU Free
+ * Documentation License.
*/
#include <linux/parport.h>
*
* This file is responsible for IEEE 1284 negotiation, and for handing
* read/write requests to low-level drivers.
+ *
+ * The block comments above the functions in this file are
+ * licensed as part of the generated file
+ * Documentation/DocBook/parportbook.sgml under the GNU Free
+ * Documentation License.
*/
#include <linux/config.h>
*
* based on work by Grant Guenther <grant@torque.net>
* and Philip Blundell
+ *
+ * The block comments above the functions in this file are
+ * licensed as part of the generated file
+ * Documentation/DocBook/parportbook.sgml under the GNU Free
+ * Documentation License.
*/
#undef PARPORT_DEBUG_SHARING /* undef for production */
#include <linux/poll.h>
#include <linux/vmalloc.h>
#include <asm/uaccess.h>
+#include <linux/smp_lock.h>
#include <linux/isapnp.h>
struct isapnp_info_buffer {
kfree(buffer);
return -ENOMEM;
}
+ lock_kernel();
buffer->curr = buffer->buffer;
file->private_data = buffer;
- MOD_INC_USE_COUNT;
if (mode == O_RDONLY)
isapnp_info_read(buffer);
+ unlock_kernel();
return 0;
}
isapnp_info_write(buffer);
vfree(buffer->buffer);
kfree(buffer);
- MOD_DEC_USE_COUNT;
return 0;
}
if (!e)
return -ENOMEM;
e->proc_fops = &isapnp_proc_bus_file_operations;
+ e->owner = THIS_MODULE;
e->data = dev;
e->size = 256;
return 0;
isapnp_proc_entry = NULL;
p = create_proc_entry("isapnp", S_IFREG | S_IRUGO | S_IWUSR, &proc_root);
- if (p)
+ if (p) {
p->proc_fops = &isapnp_info_entry_operations;
+ p->owner = THIS_MODULE;
+ }
isapnp_proc_entry = p;
isapnp_proc_bus_dir = proc_mkdir("isapnp", proc_bus);
isapnp_proc_devices_entry = create_proc_info_entry("devices", 0,
}
for (i = 0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) {
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(SD_MAJOR(i)));
blk_size[SD_MAJOR(i)] = NULL;
hardsect_size[SD_MAJOR(i)] = NULL;
read_ahead[SD_MAJOR(i)] = 0;
#ifdef DEBUG
-static void uhci_show_qh (puhci_desc_t qh)
+static void __attribute__((__unused__)) uhci_show_qh (puhci_desc_t qh)
{
if (qh->type != QH_TYPE) {
dbg("qh has not QH_TYPE");
(td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : "Breadth first"));
}
#ifdef DEBUG
-static void uhci_show_td_queue (puhci_desc_t td)
+static void __attribute__((__unused__)) uhci_show_td_queue (puhci_desc_t td)
{
//dbg("uhci_show_td_queue %p (%08lX):", td, virt_to_bus (td));
while (1) {
}
}
-static void uhci_show_queue (puhci_desc_t qh)
+static void __attribute__((__unused__)) uhci_show_queue (puhci_desc_t qh)
{
uhci_desc_t *start_qh=qh;
}
}
-static void uhci_show_sc (int port, unsigned short status)
+static void __attribute__((__unused__)) uhci_show_sc (int port, unsigned short status)
{
dbg(" stat%d = %04x %s%s%s%s%s%s%s%s",
port,
#include <linux/string.h>
#include <linux/locks.h>
#include <linux/mm.h>
+#include <linux/smp_lock.h>
#include "adfs.h"
struct super_block *sb = inode->i_sb;
struct object_info obj;
+ lock_kernel();
obj.file_id = inode->i_ino;
obj.name_len = 0;
obj.parent_id = inode->u.adfs_i.parent_id;
obj.size = inode->i_size;
adfs_dir_update(sb, &obj);
+ unlock_kernel();
}
#include <linux/major.h>
#include <linux/blkdev.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
if (!inode->i_nlink)
return;
+ lock_kernel();
if (!(bh = bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)))) {
affs_error(inode->i_sb,"write_inode","Cannot read block %lu",inode->i_ino);
+ unlock_kernel();
return;
}
file_end = GET_END_PTR(struct file_end, bh->b_data,AFFS_I2BSIZE(inode));
affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
mark_buffer_dirty(bh,1);
brelse(bh);
+ unlock_kernel();
}
int
pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n",
inode->i_ino,inode->i_nlink);
+ lock_kernel();
affs_free_prealloc(inode);
if (atomic_read(&inode->i_count) == 1) {
unsigned long cache_page = (unsigned long) inode->u.affs_i.i_ec;
free_page(cache_page);
}
}
+ unlock_kernel();
}
void
affs_delete_inode(struct inode *inode)
{
pr_debug("AFFS: delete_inode(ino=%lu, nlink=%u)\n",inode->i_ino,inode->i_nlink);
+ lock_kernel();
inode->i_size = 0;
if (S_ISREG(inode->i_mode) && !inode->u.affs_i.i_hlink)
affs_truncate(inode);
affs_free_block(inode->i_sb,inode->i_ino);
+ unlock_kernel();
clear_inode(inode);
}
#include <linux/init.h>
#include <linux/locks.h>
#include <linux/bfs_fs.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
return;
}
+ lock_kernel();
block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
bh = bread(dev, block, BFS_BSIZE);
if (!bh) {
printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino);
+ unlock_kernel();
return;
}
mark_buffer_dirty(bh, 0);
brelse(bh);
+ unlock_kernel();
}
static void bfs_delete_inode(struct inode * inode)
inode->i_size = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ lock_kernel();
mark_inode_dirty(inode);
block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
bh = bread(dev, block, BFS_BSIZE);
if (!bh) {
printf("Unable to read inode %s:%08lx\n", bdevname(dev), ino);
+ unlock_kernel();
return;
}
off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
s->su_lf_eblk = inode->iu_sblock - 1;
mark_buffer_dirty(s->su_sbh, 1);
}
+ unlock_kernel();
clear_inode(inode);
}
#include <linux/malloc.h>
#include <linux/kmod.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
int ret = -ENODEV;
struct block_device *bdev = inode->i_bdev;
down(&bdev->bd_sem);
+ lock_kernel();
if (!bdev->bd_op)
bdev->bd_op = get_blkfops(MAJOR(inode->i_rdev));
if (bdev->bd_op) {
else if (!atomic_read(&bdev->bd_openers))
bdev->bd_op = NULL;
}
+ unlock_kernel();
up(&bdev->bd_sem);
return ret;
}
unsigned short coda_flags = coda_flags_to_cflags(flags);
struct coda_cred *cred;
+ lock_kernel();
ENTRY;
coda_vfs_stat.open++;
if (error) {
CDEBUG(D_FILE, "venus: dev %d, inode %ld, out->result %d\n",
dev, (long)ino, error);
+ unlock_kernel();
return error;
}
printk("coda_open: coda_inode_grab error %d.", error);
if (cont_inode)
iput(cont_inode);
+ unlock_kernel();
return error;
}
cont_inode->i_ino, atomic_read(&cont_inode->i_count),
cont_inode->i_op);
EXIT;
+ unlock_kernel();
return 0;
}
return 0;
}
+/* This should be called _only_ with dcache_lock held */
+
+static inline struct dentry * __dget_locked(struct dentry *dentry)
+{
+ atomic_inc(&dentry->d_count);
+ if (atomic_read(&dentry->d_count) == 1) {
+ dentry_stat.nr_unused--;
+ list_del(&dentry->d_lru);
+ INIT_LIST_HEAD(&dentry->d_lru); /* make "list_empty()" work */
+ }
+ return dentry;
+}
+
+struct dentry * dget_locked(struct dentry *dentry)
+{
+ return __dget_locked(dentry);
+}
+
/**
* d_find_alias - grab a hashed alias of inode
* @inode: inode in question
next = tmp->next;
alias = list_entry(tmp, struct dentry, d_alias);
if (!list_empty(&alias->d_hash)) {
- dget(alias);
+ __dget_locked(alias);
spin_unlock(&dcache_lock);
return alias;
}
while ((tmp = tmp->next) != head) {
struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
if (!atomic_read(&dentry->d_count)) {
- dget(dentry);
+ __dget_locked(dentry);
spin_unlock(&dcache_lock);
d_drop(dentry);
dput(dentry);
if (memcmp(dentry->d_name.name, str, len))
continue;
}
- atomic_inc(&dentry->d_count);
- if (atomic_read(&dentry->d_count) == 1) {
- dentry_stat.nr_unused--;
- list_del(&dentry->d_lru);
- INIT_LIST_HEAD(&dentry->d_lru); /* make "list_empty()" work */
- }
+ __dget_locked(dentry);
spin_unlock(&dcache_lock);
return dentry;
}
lhp = base;
while ((lhp = lhp->next) != base) {
if (dentry == list_entry(lhp, struct dentry, d_hash)) {
- dget(dentry);
+ __dget_locked(dentry);
goto out;
}
}
if (!sb->s_dev)
continue;
if (sb->s_root == dentry) {
- dget(dentry);
+ __dget_locked(dentry);
goto out;
}
}
{
struct dentry *dentry;
+ spin_lock(&dcache_lock);
dentry = de->inode.dentry;
if (dentry != NULL)
{
- dget (dentry);
+ dget_locked (dentry);
de->inode.dentry = NULL;
+ spin_unlock(&dcache_lock);
/* Forcefully remove the inode */
if (dentry->d_inode != NULL) dentry->d_inode->i_nlink = 0;
d_drop (dentry);
dput (dentry);
- }
+ } else
+ spin_unlock(&dcache_lock);
} /* End Function free_dentries */
if (inode->i_ino < FIRST_INODE) return;
index = inode->i_ino - FIRST_INODE;
+ lock_kernel();
if (index >= fs_info->num_inodes)
{
printk ("%s: writing inode: %lu for which there is no entry!\n",
DEVFS_NAME, inode->i_ino);
+ unlock_kernel();
return;
}
de = fs_info->table[index];
de->inode.atime = inode->i_atime;
de->inode.mtime = inode->i_mtime;
de->inode.ctime = inode->i_ctime;
+ unlock_kernel();
} /* End Function devfs_write_inode */
static int devfs_notify_change (struct dentry *dentry, struct iattr *iattr)
struct devfs_entry *de;
struct fs_info *fs_info = inode->i_sb->u.generic_sbp;
+ lock_kernel();
de = get_devfs_entry_from_vfs_inode (inode);
- if (de == NULL) return -ENODEV;
- if ( S_ISDIR (de->mode) ) return 0;
+ err = -ENODEV;
+ if (de == NULL)
+ goto out;
+ err = 0;
+ if ( S_ISDIR (de->mode) )
+ goto out;
df = &de->u.fcb;
- if (!de->registered) return -ENODEV;
+ err = -ENODEV;
+ if (!de->registered)
+ goto out;
file->private_data = de->info;
if ( S_ISBLK (inode->i_mode) )
{
if ( S_ISCHR (inode->i_mode) ) err = chrdev_open (inode, file);
else err = -ENODEV;
}
- if (err < 0) return err;
+ if (err < 0) goto out;
/* Open was successful */
- if (df->open) return 0;
+ err = 0;
+ if (df->open) goto out;
df->open = TRUE; /* This is the first open */
if (df->auto_owner)
{
if (df->aopen_notify)
devfsd_notify_one (de, DEVFSD_NOTIFY_ASYNC_OPEN, inode->i_mode,
current->euid, current->egid, fs_info);
- return 0;
+out:
+ unlock_kernel();
+ return err;
} /* End Function devfs_open */
static struct file_operations devfs_fops =
#include <linux/fcntl.h>
#include <linux/errno.h>
#include <linux/module.h>
+#include <linux/smp_lock.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
{
int ret = -ENODEV;
+ lock_kernel();
filp->f_op = fops_get(get_chrfops(MAJOR(inode->i_rdev),
MINOR(inode->i_rdev)));
if (filp->f_op) {
if (filp->f_op->open != NULL)
ret = filp->f_op->open(inode,filp);
}
+ unlock_kernel();
return ret;
}
unlock_kernel();
return;
no_delete:
- clear_inode(inode); /* We must guarantee clearing of inode... */
unlock_kernel();
+ clear_inode(inode); /* We must guarantee clearing of inode... */
}
#define inode_bmap(inode, nr) (le32_to_cpu((inode)->u.ext2_i.i_data[(nr)]))
EXPORT_SYMBOL(fat_add_entries);
EXPORT_SYMBOL(fat_dir_empty);
EXPORT_SYMBOL(fat_truncate);
+EXPORT_SYMBOL(fat_brelse);
static int __init init_fat_fs(void)
{
#include <linux/locks.h>
#include <linux/fat_cvf.h>
#include <linux/malloc.h>
+#include <linux/smp_lock.h>
#include "msbuffer.h"
void fat_delete_inode(struct inode *inode)
{
+ lock_kernel();
inode->i_size = 0;
fat_truncate(inode);
+ unlock_kernel();
clear_inode(inode);
}
void fat_clear_inode(struct inode *inode)
{
+ lock_kernel();
spin_lock(&fat_inode_lock);
fat_cache_inval_inode(inode);
list_del(&MSDOS_I(inode)->i_fat_hash);
spin_unlock(&fat_inode_lock);
+ unlock_kernel();
}
void fat_put_super(struct super_block *sb)
retry:
i_pos = MSDOS_I(inode)->i_location;
- if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) return;
+ if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {
+ return;
+ }
if (!(bh = fat_bread(sb, i_pos >> MSDOS_DPB_BITS))) {
printk("dev = %s, ino = %d\n", kdevname(inode->i_dev), i_pos);
fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block");
+ unlock_kernel();
return;
}
spin_lock(&fat_inode_lock);
if (i_pos != MSDOS_I(inode)->i_location) {
spin_unlock(&fat_inode_lock);
fat_brelse(sb, bh);
+ unlock_kernel();
goto retry;
}
spin_unlock(&fat_inode_lock);
fat_mark_buffer_dirty(sb, bh, 1);
fat_brelse(sb, bh);
+ unlock_kernel();
}
#include <linux/mm.h>
#include <linux/malloc.h>
+#include <linux/smp_lock.h>
static void wait_for_partner(struct inode* inode, unsigned int* cnt)
{
int ret;
ret = -ERESTARTSYS;
+ lock_kernel();
if (down_interruptible(PIPE_SEM(*inode)))
goto err_nolock_nocleanup;
/* Ok! */
up(PIPE_SEM(*inode));
+ unlock_kernel();
return 0;
err_rd:
up(PIPE_SEM(*inode));
err_nolock_nocleanup:
+ unlock_kernel();
return ret;
}
#ifndef CONFIG_NFSD
#ifdef CONFIG_NFSD_MODULE
-int (*do_nfsservctl)(int, void *, void *);
+long (*do_nfsservctl)(int, void *, void *);
#endif
long
asmlinkage sys_nfsservctl(int cmd, void *argp, void *resp)
#include <linux/hfs_fs_sb.h>
#include <linux/hfs_fs_i.h>
#include <linux/hfs_fs.h>
+#include <linux/smp_lock.h>
/*================ Variable-like macros ================*/
{
struct hfs_cat_entry *entry = HFS_I(inode)->entry;
+ lock_kernel();
hfs_cat_put(entry);
if (atomic_read(&inode->i_count) == 1) {
struct hfs_hdr_layout *tmp = HFS_I(inode)->layout;
HFS_DELETE(tmp);
}
}
+ unlock_kernel();
}
/*
*/
#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include "hpfs_fn.h"
+/* HUH? */
int hpfs_open(struct inode *i, struct file *f)
{
+ lock_kernel();
hpfs_lock_inode(i);
hpfs_unlock_inode(i); /* make sure nobody is deleting the file */
+ unlock_kernel();
if (!i->i_nlink) return -ENOENT;
return 0;
}
* inode VFS functions
*/
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include "hpfs_fn.h"
static struct file_operations hpfs_file_ops =
void hpfs_delete_inode(struct inode *inode)
{
+ lock_kernel();
hpfs_remove_fnode(inode->i_sb, inode->i_ino);
+ unlock_kernel();
clear_inode(inode);
}
static struct file_operations jffs_dir_operations =
{
- readdir: jffs_readdir,
+ read: generic_read_dir,
+ readdir: jffs_readdir,
};
static struct inode_operations jffs_dir_inode_operations =
inode->i_size = 0;
+ unlock_kernel();
clear_inode(inode);
- unlock_kernel();
}
void
dent = list_entry(next, struct dentry, d_child);
if ((unsigned long)dent->d_fsdata == fpos) {
if (dent->d_inode)
- dget(dent);
+ dget_locked(dent);
else
dent = NULL;
spin_unlock(&dcache_lock);
*/
int nfs_open(struct inode *inode, struct file *filp)
{
- struct rpc_auth *auth = NFS_CLIENT(inode)->cl_auth;
- struct rpc_cred *cred = rpcauth_lookupcred(auth, 0);
+ struct rpc_auth *auth;
+ struct rpc_cred *cred;
+ lock_kernel();
+ auth = NFS_CLIENT(inode)->cl_auth;
+ cred = rpcauth_lookupcred(auth, 0);
filp->private_data = cred;
+ unlock_kernel();
return 0;
}
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(result);
+ dget_locked(result);
spin_unlock(&dcache_lock);
iput(inode);
return result;
pdentry = list_entry(aliases->prev, struct dentry, d_alias);
if (pdentry == tdentry)
pdentry = NULL;
- if (pdentry) dget(pdentry);
+ if (pdentry) dget_locked(pdentry);
}
spin_unlock(&dcache_lock);
if (pdentry == NULL) {
for (lp = child->d_inode->i_dentry.next; lp != &child->d_inode->i_dentry ; lp=lp->next) {
tmp = list_entry(lp,struct dentry, d_alias);
if (tmp->d_parent == parent) {
- child = dget(tmp);
+ child = dget_locked(tmp);
spin_unlock(&dcache_lock);
goto out;
}
#include <linux/nls.h>
#include <linux/locks.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
/* Forward declarations */
static struct inode_operations ntfs_dir_inode_operations;
static void
ntfs_write_inode (struct inode *ino, int unused)
{
+ lock_kernel();
ntfs_debug (DEBUG_LINUX, "ntfs:write inode %x\n", ino->i_ino);
ntfs_update_inode (NTFS_LINO2NINO (ino));
+ unlock_kernel();
}
#endif
static void _ntfs_clear_inode(struct inode *ino)
{
+ lock_kernel();
ntfs_debug(DEBUG_OTHER, "ntfs_clear_inode %lx\n",ino->i_ino);
#ifdef NTFS_IN_LINUX_KERNEL
if(ino->i_ino!=FILE_MFT)
ino->u.generic_ip=0;
}
#endif
+ unlock_kernel();
return;
}
if (inode->i_sb)
file_move(f, &inode->i_sb->s_files);
if (f->f_op && f->f_op->open) {
- lock_kernel();
error = f->f_op->open(inode,f);
- unlock_kernel();
if (error)
goto cleanup_all;
}
static int
pipe_rdwr_open(struct inode *inode, struct file *filp)
{
+ lock_kernel();
down(PIPE_SEM(*inode));
if (filp->f_mode & FMODE_READ)
PIPE_READERS(*inode)++;
if (filp->f_mode & FMODE_WRITE)
PIPE_WRITERS(*inode)++;
up(PIPE_SEM(*inode));
+ unlock_kernel();
return 0;
}
{"locks", locks_read_proc},
{"mounts", mounts_read_proc},
{"swaps", swaps_read_proc},
- {"slabinfo", slabinfo_read_proc},
{"iomem", memory_read_proc},
{"execdomains", execdomains_read_proc},
{NULL,NULL}
#include <linux/locks.h>
#include <linux/init.h>
#include <linux/highuid.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
static void qnx4_delete_inode(struct inode *inode)
{
QNX4DEBUG(("qnx4: deleting inode [%lu]\n", (unsigned long) inode->i_ino));
+ lock_kernel();
inode->i_size = 0;
qnx4_truncate(inode);
qnx4_free_inode(inode);
+ unlock_kernel();
}
static void qnx4_write_super(struct super_block *sb)
}
QNX4DEBUG(("qnx4: write inode 2.\n"));
block = ino / QNX4_INODES_PER_BLOCK;
+ lock_kernel();
if (!(bh = bread(inode->i_dev, block, QNX4_BLOCK_SIZE))) {
printk("qnx4: major problem: unable to read inode from dev "
"%s\n", kdevname(inode->i_dev));
+ unlock_kernel();
return;
}
raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
raw_inode->di_first_xtnt.xtnt_size = cpu_to_le32(inode->i_blocks);
mark_buffer_dirty(bh, 1);
brelse(bh);
+ unlock_kernel();
}
#endif
smb_dir_open(struct inode *dir, struct file *file)
{
struct dentry *dentry = file->f_dentry;
- struct smb_sb_info *server = server_from_dentry(dentry);
+ struct smb_sb_info *server;
int error = 0;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_dir_open: (%s/%s)\n", dentry->d_parent->d_name.name,
* Directory timestamps in the core protocol aren't updated
* when a file is added, so we give them a very short TTL.
*/
+ lock_kernel();
+ server = server_from_dentry(dentry);
if (server->opt.protocol < SMB_PROTOCOL_LANMAN2)
{
unsigned long age = jiffies - dir->u.smbfs_i.oldmtime;
if (server->conn_pid)
error = smb_revalidate_inode(dentry);
+ unlock_kernel();
return error;
}
static int
smb_file_open(struct inode *inode, struct file * file)
{
+ lock_kernel();
inode->u.smbfs_i.openers++;
+ unlock_kernel();
return 0;
}
smb_delete_inode(struct inode *ino)
{
pr_debug("smb_delete_inode\n");
+ lock_kernel();
if (smb_close(ino))
printk("smb_delete_inode: could not close inode %ld\n",
ino->i_ino);
+ unlock_kernel();
clear_inode(ino);
}
static void sysv_delete_inode(struct inode *inode)
{
+ lock_kernel();
inode->i_size = 0;
sysv_truncate(inode);
sysv_free_inode(inode);
+ unlock_kernel();
}
static void sysv_put_super(struct super_block *);
void sysv_write_inode(struct inode * inode, int wait)
{
struct buffer_head *bh;
+ lock_kernel();
bh = sysv_update_inode(inode);
brelse(bh);
+ unlock_kernel();
}
int sysv_sync_inode(struct inode * inode)
/* Superblock operations */
static struct super_operations udf_sb_ops = {
- read_inode: udf_read_inode,
+ read_inode: udf_read_inode,
write_inode: udf_write_inode,
- put_inode: udf_put_inode,
+ put_inode: udf_put_inode,
delete_inode: udf_delete_inode,
- put_super: udf_put_super,
+ put_super: udf_put_super,
write_super: udf_write_super,
- statfs: udf_statfs,
- remount_fs: udf_remount_fs,
+ statfs: udf_statfs,
+ remount_fs: udf_remount_fs,
};
struct udf_options
is_directory = S_ISDIR(inode->i_mode);
DQUOT_FREE_INODE(sb, inode);
+ DQUOT_DROP(inode);
clear_inode (inode);
void ufs_write_inode (struct inode * inode, int wait)
{
+ lock_kernel();
ufs_update_inode (inode, wait);
+ unlock_kernel();
}
int ufs_sync_inode (struct inode *inode)
return ufs_update_inode (inode, 1);
}
-void ufs_put_inode (struct inode * inode)
-{
- UFSD(("ENTER & EXIT\n"))
-}
-
void ufs_delete_inode (struct inode * inode)
{
/*inode->u.ufs_i.i_dtime = CURRENT_TIME;*/
+ lock_kernel();
mark_inode_dirty(inode);
ufs_update_inode(inode, IS_SYNC(inode));
inode->i_size = 0;
if (inode->i_blocks)
ufs_truncate (inode);
ufs_free_inode (inode);
+ unlock_kernel();
}
static struct super_operations ufs_super_ops = {
read_inode: ufs_read_inode,
write_inode: ufs_write_inode,
- put_inode: ufs_put_inode,
delete_inode: ufs_delete_inode,
put_super: ufs_put_super,
write_super: ufs_write_super,
/* Allocation counts.. */
/**
- * dget - get a reference to a dentry
+ * dget, dget_locked - get a reference to a dentry
* @dentry: dentry to get a reference to
*
* Given a dentry or %NULL pointer increment the reference count
* if appropriate and return the dentry. A dentry will not be
- * destroyed when it has references.
+ * destroyed when it has references. dget() should never be
+ * called for dentries with zero reference counter. For these cases
+ * (preferably none, functions in dcache.c are sufficient for normal
+ * needs and they take necessary precautions) you should hold dcache_lock
+ * and call dget_locked() instead of dget().
*/
static __inline__ struct dentry * dget(struct dentry *dentry)
{
- if (!atomic_read(&dentry->d_count))
- BUG();
- if (dentry)
+ if (dentry) {
+ if (!atomic_read(&dentry->d_count))
+ BUG();
atomic_inc(&dentry->d_count);
+ }
return dentry;
}
+extern struct dentry * dget_locked(struct dentry *);
+
/**
* d_unhashed - is dentry hashed
* @dentry: entry to check
/* $Id: parport.h,v 1.1 1998/05/17 10:57:52 andrea Exp andrea $ */
+/*
+ * The block comments above the functions in this file are
+ * licensed as part of the generated file
+ * Documentation/DocBook/parportbook.sgml under the GNU Free
+ * Documentation License.
+ */
+
#ifndef _PARPORT_H_
#define _PARPORT_H_
static void shm_put_super (struct super_block *);
static int shm_remount_fs (struct super_block *, int *, char *);
static void shm_read_inode (struct inode *);
-static void shm_write_inode(struct inode *, int);
static int shm_statfs (struct super_block *, struct statfs *);
static int shm_create (struct inode *,struct dentry *,int);
static struct dentry *shm_lookup (struct inode *,struct dentry *);
static struct super_operations shm_sops = {
read_inode: shm_read_inode,
- write_inode: shm_write_inode,
delete_inode: shm_delete,
put_super: shm_put_super,
statfs: shm_statfs,
return 0;
}
-static void shm_write_inode(struct inode * inode, int sync)
-{
-}
-
static void shm_read_inode(struct inode * inode)
{
int id;
return err;
}
+/* FIXME: maybe we need lock_kernel() here */
static void shm_delete (struct inode *ino)
{
int shmid = ino->i_ino;
#ifdef CONFIG_BSD_PROCESS_ACCT
#include <linux/mm.h>
+#include <linux/slab.h>
#include <linux/acct.h>
#include <linux/smp_lock.h>
#include <linux/file.h>
extern int console_loglevel;
extern void set_device_ro(kdev_t dev,int flag);
#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
-extern int (*do_nfsservctl)(int, void *, void *);
+extern long (*do_nfsservctl)(int, void *, void *);
#endif
extern void *sys_call_table;
EXPORT_SYMBOL(dcache_lock);
EXPORT_SYMBOL(d_alloc_root);
EXPORT_SYMBOL(d_delete);
+EXPORT_SYMBOL(dget_locked);
EXPORT_SYMBOL(d_validate);
EXPORT_SYMBOL(d_rehash);
EXPORT_SYMBOL(d_invalidate); /* May be it will be better in dcache.h? */
*/
static void filemap_unmap(struct vm_area_struct *vma, unsigned long start, size_t len)
{
- lock_kernel();
filemap_sync(vma, start, len, MS_ASYNC);
- unlock_kernel();
}
/*
{
if (vma->vm_file && vma->vm_ops && vma->vm_ops->sync) {
int error;
- lock_kernel();
error = vma->vm_ops->sync(vma, start, end-start, flags);
if (!error && (flags & MS_SYNC)) {
struct file * file = vma->vm_file;
- if (file && file->f_op && file->f_op->fsync)
+ if (file && file->f_op && file->f_op->fsync) {
+ down(&file->f_dentry->d_inode->i_sem);
+ lock_kernel();
error = file->f_op->fsync(file, file->f_dentry, 1);
+ unlock_kernel();
+ up(&file->f_dentry->d_inode->i_sem);
+ }
}
- unlock_kernel();
return error;
}
return 0;
flags: SLAB_NO_REAP,
spinlock: SPIN_LOCK_UNLOCKED,
colour_off: L1_CACHE_BYTES,
- name: "kmem_cache"
+ name: "kmem_cache",
+ next: LIST_HEAD_INIT(cache_cache.next)
};
/* Guard access to the cache-chain. */
return -ENOMEM;
}
p->proc_fops = &mpc_file_operations;
+ p->owner = THIS_MODULE;
return 0;
}
goto fail0;
dev->proc_entry->data = dev;
dev->proc_entry->proc_fops = &proc_dev_atm_operations;
+ dev->proc_entry->owner = THIS_MODULE;
return 0;
kfree(dev->proc_entry);
fail0:
name = create_proc_entry(#name,0,atm_proc_root); \
if (!name) goto cleanup; \
name->data = atm_##name##_info; \
- name->proc_fops = &proc_spec_atm_operations
+ name->proc_fops = &proc_spec_atm_operations; \
+ name->owner = THIS_MODULE
int __init atm_proc_init(void)
#endif /* CONFIG_INET */
-#if defined(CONFIG_ULTRA) || defined(CONFIG_WD80x3) || \
- defined(CONFIG_EL2) || defined(CONFIG_NE2000) || \
- defined(CONFIG_E2100) || defined(CONFIG_HPLAN_PLUS) || \
- defined(CONFIG_HPLAN) || defined(CONFIG_AC3200) || \
- defined(CONFIG_ES3210) || defined(CONFIG_ULTRA32) || \
- defined(CONFIG_LNE390) || defined(CONFIG_NE3210) || \
- defined(CONFIG_NE2K_PCI) || defined(CONFIG_APNE) || \
- defined(CONFIG_DAYNAPORT)
-/* If 8390 NIC support is built in, we will need these. */
-EXPORT_SYMBOL(ei_open);
-EXPORT_SYMBOL(ei_close);
-EXPORT_SYMBOL(ei_interrupt);
-EXPORT_SYMBOL(ethdev_init);
-EXPORT_SYMBOL(NS8390_init);
-#endif
-
#ifdef CONFIG_TR
EXPORT_SYMBOL(tr_setup);
EXPORT_SYMBOL(tr_type_trans);
file->f_vfsmnt = mntget(sock_mnt);
sock->file = file;
- file->f_op = &socket_file_ops;
+ file->f_op = sock->inode->i_fop = &socket_file_ops;
file->f_mode = 3;
file->f_flags = O_RDWR;
file->f_pos = 0;