Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs updates from Al Viro: "Assorted cleanups and fixes. Probably the most interesting part long-term is ->d_init() - that will have a bunch of followups in (at least) ceph and lustre, but we'll need to sort the barrier-related rules before it can get used for really non-trivial stuff. Another fun thing is the merge of ->d_iput() callers (dentry_iput() and dentry_unlink_inode()) and a bunch of ->d_compare() ones (all except the one in __d_lookup_lru())" * 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (26 commits) fs/dcache.c: avoid soft-lockup in dput() vfs: new d_init method vfs: Update lookup_dcache() comment bdev: get rid of ->bd_inodes Remove last traces of ->sync_page new helper: d_same_name() dentry_cmp(): use lockless_dereference() instead of smp_read_barrier_depends() vfs: clean up documentation vfs: document ->d_real() vfs: merge .d_select_inode() into .d_real() unify dentry_iput() and dentry_unlink_inode() binfmt_misc: ->s_root is not going anywhere drop redundant ->owner initializations ufs: get rid of redundant checks orangefs: constify inode_operations missed comment updates from ->direct_IO() prototype change file_inode(f)->i_mapping is f->f_mapping trim fsnotify hooks a bit 9p: new helper - v9fs_parent_fid() debugfs: ->d_parent is never NULL or negative ...
This commit is contained in:
@@ -15,11 +15,14 @@ prototypes:
|
||||
int (*d_compare)(const struct dentry *, const struct dentry *,
|
||||
unsigned int, const char *, const struct qstr *);
|
||||
int (*d_delete)(struct dentry *);
|
||||
int (*d_init)(struct dentry *);
|
||||
void (*d_release)(struct dentry *);
|
||||
void (*d_iput)(struct dentry *, struct inode *);
|
||||
char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
|
||||
struct vfsmount *(*d_automount)(struct path *path);
|
||||
int (*d_manage)(struct dentry *, bool);
|
||||
struct dentry *(*d_real)(struct dentry *, const struct inode *,
|
||||
unsigned int);
|
||||
|
||||
locking rules:
|
||||
rename_lock ->d_lock may block rcu-walk
|
||||
@@ -28,12 +31,14 @@ d_weak_revalidate:no no yes no
|
||||
d_hash no no no maybe
|
||||
d_compare: yes no no maybe
|
||||
d_delete: no yes no no
|
||||
d_init: no no yes no
|
||||
d_release: no no yes no
|
||||
d_prune: no yes no no
|
||||
d_iput: no no yes no
|
||||
d_dname: no no no no
|
||||
d_automount: no no yes no
|
||||
d_manage: no no yes (ref-walk) maybe
|
||||
d_real no no yes no
|
||||
|
||||
--------------------------- inode_operations ---------------------------
|
||||
prototypes:
|
||||
@@ -66,7 +71,6 @@ prototypes:
|
||||
struct file *, unsigned open_flag,
|
||||
umode_t create_mode, int *opened);
|
||||
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
|
||||
int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
|
||||
|
||||
locking rules:
|
||||
all may block
|
||||
@@ -95,7 +99,6 @@ fiemap: no
|
||||
update_time: no
|
||||
atomic_open: yes
|
||||
tmpfile: no
|
||||
dentry_open: no
|
||||
|
||||
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
|
||||
victim.
|
||||
@@ -179,7 +182,6 @@ unlocks and drops the reference.
|
||||
prototypes:
|
||||
int (*writepage)(struct page *page, struct writeback_control *wbc);
|
||||
int (*readpage)(struct file *, struct page *);
|
||||
int (*sync_page)(struct page *);
|
||||
int (*writepages)(struct address_space *, struct writeback_control *);
|
||||
int (*set_page_dirty)(struct page *page);
|
||||
int (*readpages)(struct file *filp, struct address_space *mapping,
|
||||
@@ -210,7 +212,6 @@ locking rules:
|
||||
PageLocked(page) i_mutex
|
||||
writepage: yes, unlocks (see below)
|
||||
readpage: yes, unlocks
|
||||
sync_page: maybe
|
||||
writepages:
|
||||
set_page_dirty no
|
||||
readpages:
|
||||
@@ -230,8 +231,8 @@ error_remove_page: yes
|
||||
swap_activate: no
|
||||
swap_deactivate: no
|
||||
|
||||
->write_begin(), ->write_end(), ->sync_page() and ->readpage()
|
||||
may be called from the request handler (/dev/loop).
|
||||
->write_begin(), ->write_end() and ->readpage() may be called from
|
||||
the request handler (/dev/loop).
|
||||
|
||||
->readpage() unlocks the page, either synchronously or via I/O
|
||||
completion.
|
||||
@@ -287,11 +288,6 @@ will leave the page itself marked clean but it will be tagged as dirty in the
|
||||
radix tree. This incoherency can lead to all sorts of hard-to-debug problems
|
||||
in the filesystem like having dirty inodes at umount and losing written data.
|
||||
|
||||
->sync_page() locking rules are not well-defined - usually it is called
|
||||
with lock on page, but that is not guaranteed. Considering the currently
|
||||
existing instances of this method ->sync_page() itself doesn't look
|
||||
well-defined...
|
||||
|
||||
->writepages() is used for periodic writeback and for syscall-initiated
|
||||
sync operations. The address_space should start I/O against at least
|
||||
*nr_to_write pages. *nr_to_write must be decremented for each page which is
|
||||
|
@@ -364,7 +364,6 @@ struct inode_operations {
|
||||
int (*atomic_open)(struct inode *, struct dentry *, struct file *,
|
||||
unsigned open_flag, umode_t create_mode, int *opened);
|
||||
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
|
||||
int (*dentry_open)(struct dentry *, struct file *, const struct cred *);
|
||||
};
|
||||
|
||||
Again, all methods are called without any locks being held, unless
|
||||
@@ -534,9 +533,7 @@ __sync_single_inode) to check if ->writepages has been successful in
|
||||
writing out the whole address_space.
|
||||
|
||||
The Writeback tag is used by filemap*wait* and sync_page* functions,
|
||||
via filemap_fdatawait_range, to wait for all writeback to
|
||||
complete. While waiting ->sync_page (if defined) will be called on
|
||||
each page that is found to require writeback.
|
||||
via filemap_fdatawait_range, to wait for all writeback to complete.
|
||||
|
||||
An address_space handler may attach extra information to a page,
|
||||
typically using the 'private' field in the 'struct page'. If such
|
||||
@@ -554,8 +551,8 @@ address_space has finer control of write sizes.
|
||||
|
||||
The read process essentially only requires 'readpage'. The write
|
||||
process is more complicated and uses write_begin/write_end or
|
||||
set_page_dirty to write data into the address_space, and writepage,
|
||||
sync_page, and writepages to writeback data to storage.
|
||||
set_page_dirty to write data into the address_space, and writepage
|
||||
and writepages to writeback data to storage.
|
||||
|
||||
Adding and removing pages to/from an address_space is protected by the
|
||||
inode's i_mutex.
|
||||
@@ -701,13 +698,6 @@ struct address_space_operations {
|
||||
but instead uses bmap to find out where the blocks in the file
|
||||
are and uses those addresses directly.
|
||||
|
||||
dentry_open: *WARNING: probably going away soon, do not use!* This is an
|
||||
alternative to f_op->open(), the difference is that this method may open
|
||||
a file not necessarily originating from the same filesystem as the one
|
||||
i_op->open() was called on. It may be useful for stacking filesystems
|
||||
which want to allow native I/O directly on underlying files.
|
||||
|
||||
|
||||
invalidatepage: If a page has PagePrivate set, then invalidatepage
|
||||
will be called when part or all of the page is to be removed
|
||||
from the address space. This generally corresponds to either a
|
||||
@@ -944,11 +934,14 @@ struct dentry_operations {
|
||||
int (*d_compare)(const struct dentry *, const struct dentry *,
|
||||
unsigned int, const char *, const struct qstr *);
|
||||
int (*d_delete)(const struct dentry *);
|
||||
int (*d_init)(struct dentry *);
|
||||
void (*d_release)(struct dentry *);
|
||||
void (*d_iput)(struct dentry *, struct inode *);
|
||||
char *(*d_dname)(struct dentry *, char *, int);
|
||||
struct vfsmount *(*d_automount)(struct path *);
|
||||
int (*d_manage)(struct dentry *, bool);
|
||||
struct dentry *(*d_real)(struct dentry *, const struct inode *,
|
||||
unsigned int);
|
||||
};
|
||||
|
||||
d_revalidate: called when the VFS needs to revalidate a dentry. This
|
||||
@@ -1014,6 +1007,8 @@ struct dentry_operations {
|
||||
always cache a reachable dentry. d_delete must be constant and
|
||||
idempotent.
|
||||
|
||||
d_init: called when a dentry is allocated
|
||||
|
||||
d_release: called when a dentry is really deallocated
|
||||
|
||||
d_iput: called when a dentry loses its inode (just prior to its
|
||||
@@ -1033,6 +1028,14 @@ struct dentry_operations {
|
||||
at the end of the buffer, and returns a pointer to the first char.
|
||||
dynamic_dname() helper function is provided to take care of this.
|
||||
|
||||
Example :
|
||||
|
||||
static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen)
|
||||
{
|
||||
return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]",
|
||||
dentry->d_inode->i_ino);
|
||||
}
|
||||
|
||||
d_automount: called when an automount dentry is to be traversed (optional).
|
||||
This should create a new VFS mount record and return the record to the
|
||||
caller. The caller is supplied with a path parameter giving the
|
||||
@@ -1071,13 +1074,23 @@ struct dentry_operations {
|
||||
This function is only used if DCACHE_MANAGE_TRANSIT is set on the
|
||||
dentry being transited from.
|
||||
|
||||
Example :
|
||||
d_real: overlay/union type filesystems implement this method to return one of
|
||||
the underlying dentries hidden by the overlay. It is used in three
|
||||
different modes:
|
||||
|
||||
static char *pipefs_dname(struct dentry *dent, char *buffer, int buflen)
|
||||
{
|
||||
return dynamic_dname(dentry, buffer, buflen, "pipe:[%lu]",
|
||||
dentry->d_inode->i_ino);
|
||||
}
|
||||
Called from open it may need to copy-up the file depending on the
|
||||
supplied open flags. This mode is selected with a non-zero flags
|
||||
argument. In this mode the d_real method can return an error.
|
||||
|
||||
Called from file_dentry() it returns the real dentry matching the inode
|
||||
argument. The real dentry may be from a lower layer already copied up,
|
||||
but still referenced from the file. This mode is selected with a
|
||||
non-NULL inode argument. This will always succeed.
|
||||
|
||||
With NULL inode and zero flags the topmost real underlying dentry is
|
||||
returned. This will always succeed.
|
||||
|
||||
This method is never called with both non-NULL inode and non-zero flags.
|
||||
|
||||
Each dentry has a pointer to its parent dentry, as well as a hash list
|
||||
of child dentries. Child dentries are basically like files in a
|
||||
|
Reference in New Issue
Block a user