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:
commit
6784725ab0
61 changed files with 224 additions and 413 deletions
|
@ -1024,8 +1024,7 @@ could be on demand. For example wait_on_buffer sets the unplugging going
|
|||
through sync_buffer() running blk_run_address_space(mapping). Or the caller
|
||||
can do it explicity through blk_unplug(bdev). So in the read case,
|
||||
the queue gets explicitly unplugged as part of waiting for completion on that
|
||||
buffer. For page driven IO, the address space ->sync_page() takes care of
|
||||
doing the blk_run_address_space().
|
||||
buffer.
|
||||
|
||||
Aside:
|
||||
This is kind of controversial territory, as it's not clear if plugging is
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -425,9 +425,6 @@ static int drbd_single_open(struct file *file, int (*show)(struct seq_file *, vo
|
|||
/* Are we still linked,
|
||||
* or has debugfs_remove() already been called? */
|
||||
parent = file->f_path.dentry->d_parent;
|
||||
/* not sure if this can happen: */
|
||||
if (!parent || d_really_is_negative(parent))
|
||||
goto out;
|
||||
/* serialize with d_delete() */
|
||||
inode_lock(d_inode(parent));
|
||||
/* Make sure the object is still alive */
|
||||
|
@ -440,7 +437,6 @@ static int drbd_single_open(struct file *file, int (*show)(struct seq_file *, vo
|
|||
if (ret)
|
||||
kref_put(kref, release);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ struct armada_gem_object *armada_gem_alloc_object(struct drm_device *dev,
|
|||
|
||||
obj->dev_addr = DMA_ERROR_CODE;
|
||||
|
||||
mapping = file_inode(obj->obj.filp)->i_mapping;
|
||||
mapping = obj->obj.filp->f_mapping;
|
||||
mapping_set_gfp_mask(mapping, GFP_HIGHUSER | __GFP_RECLAIMABLE);
|
||||
|
||||
DRM_DEBUG_DRIVER("alloc obj %p size %zu\n", obj, size);
|
||||
|
@ -441,7 +441,7 @@ armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
|
|||
if (sg_alloc_table(sgt, count, GFP_KERNEL))
|
||||
goto free_sgt;
|
||||
|
||||
mapping = file_inode(dobj->obj.filp)->i_mapping;
|
||||
mapping = dobj->obj.filp->f_mapping;
|
||||
|
||||
for_each_sg(sgt->sgl, sg, count, i) {
|
||||
struct page *page;
|
||||
|
|
|
@ -511,7 +511,7 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj)
|
|||
int i, npages;
|
||||
|
||||
/* This is the shared memory object that backs the GEM resource */
|
||||
mapping = file_inode(obj->filp)->i_mapping;
|
||||
mapping = obj->filp->f_mapping;
|
||||
|
||||
/* We already BUG_ON() for non-page-aligned sizes in
|
||||
* drm_gem_object_init(), so we should never hit this unless
|
||||
|
|
|
@ -660,7 +660,7 @@ static struct drm_gem_object *__etnaviv_gem_new(struct drm_device *dev,
|
|||
* why this is required _and_ expected if you're
|
||||
* going to pin these pages.
|
||||
*/
|
||||
mapping = file_inode(obj->filp)->i_mapping;
|
||||
mapping = obj->filp->f_mapping;
|
||||
mapping_set_gfp_mask(mapping, GFP_HIGHUSER);
|
||||
}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
|
|||
static int
|
||||
i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
struct address_space *mapping = file_inode(obj->base.filp)->i_mapping;
|
||||
struct address_space *mapping = obj->base.filp->f_mapping;
|
||||
char *vaddr = obj->phys_handle->vaddr;
|
||||
struct sg_table *st;
|
||||
struct scatterlist *sg;
|
||||
|
@ -218,7 +218,7 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj)
|
|||
obj->dirty = 0;
|
||||
|
||||
if (obj->dirty) {
|
||||
struct address_space *mapping = file_inode(obj->base.filp)->i_mapping;
|
||||
struct address_space *mapping = obj->base.filp->f_mapping;
|
||||
char *vaddr = obj->phys_handle->vaddr;
|
||||
int i;
|
||||
|
||||
|
@ -2155,7 +2155,7 @@ i915_gem_object_invalidate(struct drm_i915_gem_object *obj)
|
|||
if (obj->base.filp == NULL)
|
||||
return;
|
||||
|
||||
mapping = file_inode(obj->base.filp)->i_mapping,
|
||||
mapping = obj->base.filp->f_mapping,
|
||||
invalidate_mapping_pages(mapping, 0, (loff_t)-1);
|
||||
}
|
||||
|
||||
|
@ -2271,7 +2271,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
|
|||
*
|
||||
* Fail silently without starting the shrinker
|
||||
*/
|
||||
mapping = file_inode(obj->base.filp)->i_mapping;
|
||||
mapping = obj->base.filp->f_mapping;
|
||||
gfp = mapping_gfp_constraint(mapping, ~(__GFP_IO | __GFP_RECLAIM));
|
||||
gfp |= __GFP_NORETRY | __GFP_NOWARN;
|
||||
sg = st->sgl;
|
||||
|
@ -4522,7 +4522,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
|
|||
mask |= __GFP_DMA32;
|
||||
}
|
||||
|
||||
mapping = file_inode(obj->base.filp)->i_mapping;
|
||||
mapping = obj->base.filp->f_mapping;
|
||||
mapping_set_gfp_mask(mapping, mask);
|
||||
|
||||
i915_gem_object_init(obj, &i915_gem_object_ops);
|
||||
|
|
|
@ -1407,7 +1407,7 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev,
|
|||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
mapping = file_inode(obj->filp)->i_mapping;
|
||||
mapping = obj->filp->f_mapping;
|
||||
mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32);
|
||||
}
|
||||
|
||||
|
|
|
@ -298,7 +298,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
|
|||
swap_storage = ttm->swap_storage;
|
||||
BUG_ON(swap_storage == NULL);
|
||||
|
||||
swap_space = file_inode(swap_storage)->i_mapping;
|
||||
swap_space = swap_storage->f_mapping;
|
||||
|
||||
for (i = 0; i < ttm->num_pages; ++i) {
|
||||
from_page = shmem_read_mapping_page(swap_space, i);
|
||||
|
@ -347,7 +347,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
|
|||
} else
|
||||
swap_storage = persistent_swap_storage;
|
||||
|
||||
swap_space = file_inode(swap_storage)->i_mapping;
|
||||
swap_space = swap_storage->f_mapping;
|
||||
|
||||
for (i = 0; i < ttm->num_pages; ++i) {
|
||||
from_page = ttm->pages[i];
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#include <linux/list.h>
|
||||
|
||||
struct p9_fid *v9fs_fid_lookup(struct dentry *dentry);
|
||||
static inline struct p9_fid *v9fs_parent_fid(struct dentry *dentry)
|
||||
{
|
||||
return v9fs_fid_lookup(dentry->d_parent);
|
||||
}
|
||||
struct p9_fid *v9fs_fid_clone(struct dentry *dentry);
|
||||
void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
|
||||
struct p9_fid *v9fs_writeback_fid(struct dentry *dentry);
|
||||
|
|
|
@ -231,7 +231,6 @@ static int v9fs_launder_page(struct page *page)
|
|||
/**
|
||||
* v9fs_direct_IO - 9P address space operation for direct I/O
|
||||
* @iocb: target I/O control block
|
||||
* @pos: offset in file to begin the operation
|
||||
*
|
||||
* The presence of v9fs_direct_IO() in the address space ops vector
|
||||
* allowes open() O_DIRECT flags which would have failed otherwise.
|
||||
|
|
|
@ -595,7 +595,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
|
|||
|
||||
v9ses = v9fs_inode2v9ses(dir);
|
||||
inode = d_inode(dentry);
|
||||
dfid = v9fs_fid_lookup(dentry->d_parent);
|
||||
dfid = v9fs_parent_fid(dentry);
|
||||
if (IS_ERR(dfid)) {
|
||||
retval = PTR_ERR(dfid);
|
||||
p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", retval);
|
||||
|
@ -653,7 +653,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
|
|||
ofid = NULL;
|
||||
fid = NULL;
|
||||
name = (char *) dentry->d_name.name;
|
||||
dfid = v9fs_fid_lookup(dentry->d_parent);
|
||||
dfid = v9fs_parent_fid(dentry);
|
||||
if (IS_ERR(dfid)) {
|
||||
err = PTR_ERR(dfid);
|
||||
p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
|
||||
|
@ -798,7 +798,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
|
|||
|
||||
v9ses = v9fs_inode2v9ses(dir);
|
||||
/* We can walk d_parent because we hold the dir->i_mutex */
|
||||
dfid = v9fs_fid_lookup(dentry->d_parent);
|
||||
dfid = v9fs_parent_fid(dentry);
|
||||
if (IS_ERR(dfid))
|
||||
return ERR_CAST(dfid);
|
||||
|
||||
|
@ -975,13 +975,13 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
if (IS_ERR(oldfid))
|
||||
return PTR_ERR(oldfid);
|
||||
|
||||
olddirfid = v9fs_fid_clone(old_dentry->d_parent);
|
||||
olddirfid = v9fs_parent_fid(old_dentry);
|
||||
if (IS_ERR(olddirfid)) {
|
||||
retval = PTR_ERR(olddirfid);
|
||||
goto done;
|
||||
}
|
||||
|
||||
newdirfid = v9fs_fid_clone(new_dentry->d_parent);
|
||||
newdirfid = v9fs_parent_fid(new_dentry);
|
||||
if (IS_ERR(newdirfid)) {
|
||||
retval = PTR_ERR(newdirfid);
|
||||
goto clunk_olddir;
|
||||
|
|
|
@ -273,7 +273,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
|
|||
p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%hx\n",
|
||||
name, flags, omode);
|
||||
|
||||
dfid = v9fs_fid_lookup(dentry->d_parent);
|
||||
dfid = v9fs_parent_fid(dentry);
|
||||
if (IS_ERR(dfid)) {
|
||||
err = PTR_ERR(dfid);
|
||||
p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
|
||||
|
@ -389,7 +389,6 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
|
|||
umode_t mode;
|
||||
struct inode *inode;
|
||||
struct p9_qid qid;
|
||||
struct dentry *dir_dentry;
|
||||
struct posix_acl *dacl = NULL, *pacl = NULL;
|
||||
|
||||
p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry);
|
||||
|
@ -400,8 +399,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
|
|||
if (dir->i_mode & S_ISGID)
|
||||
omode |= S_ISGID;
|
||||
|
||||
dir_dentry = dentry->d_parent;
|
||||
dfid = v9fs_fid_lookup(dir_dentry);
|
||||
dfid = v9fs_parent_fid(dentry);
|
||||
if (IS_ERR(dfid)) {
|
||||
err = PTR_ERR(dfid);
|
||||
p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
|
||||
|
@ -691,7 +689,7 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
|
|||
p9_debug(P9_DEBUG_VFS, "%lu,%s,%s\n", dir->i_ino, name, symname);
|
||||
v9ses = v9fs_inode2v9ses(dir);
|
||||
|
||||
dfid = v9fs_fid_lookup(dentry->d_parent);
|
||||
dfid = v9fs_parent_fid(dentry);
|
||||
if (IS_ERR(dfid)) {
|
||||
err = PTR_ERR(dfid);
|
||||
p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
|
||||
|
@ -762,7 +760,6 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
|
|||
struct dentry *dentry)
|
||||
{
|
||||
int err;
|
||||
struct dentry *dir_dentry;
|
||||
struct p9_fid *dfid, *oldfid;
|
||||
struct v9fs_session_info *v9ses;
|
||||
|
||||
|
@ -770,8 +767,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
|
|||
dir->i_ino, old_dentry, dentry);
|
||||
|
||||
v9ses = v9fs_inode2v9ses(dir);
|
||||
dir_dentry = dentry->d_parent;
|
||||
dfid = v9fs_fid_lookup(dir_dentry);
|
||||
dfid = v9fs_parent_fid(dentry);
|
||||
if (IS_ERR(dfid))
|
||||
return PTR_ERR(dfid);
|
||||
|
||||
|
@ -822,7 +818,6 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
|
|||
struct p9_fid *fid = NULL, *dfid = NULL;
|
||||
struct inode *inode;
|
||||
struct p9_qid qid;
|
||||
struct dentry *dir_dentry;
|
||||
struct posix_acl *dacl = NULL, *pacl = NULL;
|
||||
|
||||
p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %hx MAJOR: %u MINOR: %u\n",
|
||||
|
@ -830,8 +825,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
|
|||
MAJOR(rdev), MINOR(rdev));
|
||||
|
||||
v9ses = v9fs_inode2v9ses(dir);
|
||||
dir_dentry = dentry->d_parent;
|
||||
dfid = v9fs_fid_lookup(dir_dentry);
|
||||
dfid = v9fs_parent_fid(dentry);
|
||||
if (IS_ERR(dfid)) {
|
||||
err = PTR_ERR(dfid);
|
||||
p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
|
||||
|
|
|
@ -637,13 +637,12 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
|
|||
break;
|
||||
case 3:
|
||||
/* Delete this handler. */
|
||||
root = dget(file->f_path.dentry->d_sb->s_root);
|
||||
root = file_inode(file)->i_sb->s_root;
|
||||
inode_lock(d_inode(root));
|
||||
|
||||
kill_node(e);
|
||||
|
||||
inode_unlock(d_inode(root));
|
||||
dput(root);
|
||||
break;
|
||||
default:
|
||||
return res;
|
||||
|
@ -665,8 +664,8 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
|
|||
{
|
||||
Node *e;
|
||||
struct inode *inode;
|
||||
struct dentry *root, *dentry;
|
||||
struct super_block *sb = file->f_path.dentry->d_sb;
|
||||
struct super_block *sb = file_inode(file)->i_sb;
|
||||
struct dentry *root = sb->s_root, *dentry;
|
||||
int err = 0;
|
||||
|
||||
e = create_entry(buffer, count);
|
||||
|
@ -674,7 +673,6 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
|
|||
if (IS_ERR(e))
|
||||
return PTR_ERR(e);
|
||||
|
||||
root = dget(sb->s_root);
|
||||
inode_lock(d_inode(root));
|
||||
dentry = lookup_one_len(e->name, root, strlen(e->name));
|
||||
err = PTR_ERR(dentry);
|
||||
|
@ -712,7 +710,6 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
|
|||
dput(dentry);
|
||||
out:
|
||||
inode_unlock(d_inode(root));
|
||||
dput(root);
|
||||
|
||||
if (err) {
|
||||
kfree(e);
|
||||
|
@ -753,14 +750,13 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
|
|||
break;
|
||||
case 3:
|
||||
/* Delete all handlers. */
|
||||
root = dget(file->f_path.dentry->d_sb->s_root);
|
||||
root = file_inode(file)->i_sb->s_root;
|
||||
inode_lock(d_inode(root));
|
||||
|
||||
while (!list_empty(&entries))
|
||||
kill_node(list_entry(entries.next, Node, list));
|
||||
|
||||
inode_unlock(d_inode(root));
|
||||
dput(root);
|
||||
break;
|
||||
default:
|
||||
return res;
|
||||
|
|
|
@ -614,7 +614,6 @@ static void init_once(void *foo)
|
|||
|
||||
memset(bdev, 0, sizeof(*bdev));
|
||||
mutex_init(&bdev->bd_mutex);
|
||||
INIT_LIST_HEAD(&bdev->bd_inodes);
|
||||
INIT_LIST_HEAD(&bdev->bd_list);
|
||||
#ifdef CONFIG_SYSFS
|
||||
INIT_LIST_HEAD(&bdev->bd_holder_disks);
|
||||
|
@ -624,24 +623,13 @@ static void init_once(void *foo)
|
|||
mutex_init(&bdev->bd_fsfreeze_mutex);
|
||||
}
|
||||
|
||||
static inline void __bd_forget(struct inode *inode)
|
||||
{
|
||||
list_del_init(&inode->i_devices);
|
||||
inode->i_bdev = NULL;
|
||||
inode->i_mapping = &inode->i_data;
|
||||
}
|
||||
|
||||
static void bdev_evict_inode(struct inode *inode)
|
||||
{
|
||||
struct block_device *bdev = &BDEV_I(inode)->bdev;
|
||||
struct list_head *p;
|
||||
truncate_inode_pages_final(&inode->i_data);
|
||||
invalidate_inode_buffers(inode); /* is it needed here? */
|
||||
clear_inode(inode);
|
||||
spin_lock(&bdev_lock);
|
||||
while ( (p = bdev->bd_inodes.next) != &bdev->bd_inodes ) {
|
||||
__bd_forget(list_entry(p, struct inode, i_devices));
|
||||
}
|
||||
list_del_init(&bdev->bd_list);
|
||||
spin_unlock(&bdev_lock);
|
||||
}
|
||||
|
@ -805,7 +793,6 @@ static struct block_device *bd_acquire(struct inode *inode)
|
|||
bdgrab(bdev);
|
||||
inode->i_bdev = bdev;
|
||||
inode->i_mapping = bdev->bd_inode->i_mapping;
|
||||
list_add(&inode->i_devices, &bdev->bd_inodes);
|
||||
}
|
||||
spin_unlock(&bdev_lock);
|
||||
}
|
||||
|
@ -821,7 +808,8 @@ void bd_forget(struct inode *inode)
|
|||
spin_lock(&bdev_lock);
|
||||
if (!sb_is_blkdev_sb(inode->i_sb))
|
||||
bdev = inode->i_bdev;
|
||||
__bd_forget(inode);
|
||||
inode->i_bdev = NULL;
|
||||
inode->i_mapping = &inode->i_data;
|
||||
spin_unlock(&bdev_lock);
|
||||
|
||||
if (bdev)
|
||||
|
|
|
@ -93,7 +93,6 @@ static int cachefiles_histogram_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
static const struct file_operations cachefiles_histogram_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = cachefiles_histogram_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -244,7 +244,6 @@ static int cifs_debug_data_proc_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
static const struct file_operations cifs_debug_data_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = cifs_debug_data_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
@ -361,7 +360,6 @@ static int cifs_stats_proc_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
static const struct file_operations cifs_stats_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = cifs_stats_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
@ -447,7 +445,6 @@ static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
|
|||
}
|
||||
|
||||
static const struct file_operations cifsFYI_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = cifsFYI_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
@ -479,7 +476,6 @@ static ssize_t cifs_linux_ext_proc_write(struct file *file,
|
|||
}
|
||||
|
||||
static const struct file_operations cifs_linux_ext_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = cifs_linux_ext_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
@ -511,7 +507,6 @@ static ssize_t cifs_lookup_cache_proc_write(struct file *file,
|
|||
}
|
||||
|
||||
static const struct file_operations cifs_lookup_cache_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = cifs_lookup_cache_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
@ -543,7 +538,6 @@ static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer,
|
|||
}
|
||||
|
||||
static const struct file_operations traceSMB_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = traceSMB_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
@ -655,7 +649,6 @@ static ssize_t cifs_security_flags_proc_write(struct file *file,
|
|||
}
|
||||
|
||||
static const struct file_operations cifs_security_flags_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = cifs_security_flags_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -35,7 +35,6 @@ const struct inode_operations coda_ioctl_inode_operations = {
|
|||
};
|
||||
|
||||
const struct file_operations coda_ioctl_operations = {
|
||||
.owner = THIS_MODULE,
|
||||
.unlocked_ioctl = coda_pioctl,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
|
|
190
fs/dcache.c
190
fs/dcache.c
|
@ -224,10 +224,9 @@ static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char
|
|||
|
||||
static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *ct, unsigned tcount)
|
||||
{
|
||||
const unsigned char *cs;
|
||||
/*
|
||||
* Be careful about RCU walk racing with rename:
|
||||
* use ACCESS_ONCE to fetch the name pointer.
|
||||
* use 'lockless_dereference' to fetch the name pointer.
|
||||
*
|
||||
* NOTE! Even if a rename will mean that the length
|
||||
* was not loaded atomically, we don't care. The
|
||||
|
@ -241,8 +240,8 @@ static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *c
|
|||
* early because the data cannot match (there can
|
||||
* be no NUL in the ct/tcount data)
|
||||
*/
|
||||
cs = ACCESS_ONCE(dentry->d_name.name);
|
||||
smp_read_barrier_depends();
|
||||
const unsigned char *cs = lockless_dereference(dentry->d_name.name);
|
||||
|
||||
return dentry_string_cmp(cs, ct, tcount);
|
||||
}
|
||||
|
||||
|
@ -333,43 +332,20 @@ static inline void dentry_rcuwalk_invalidate(struct dentry *dentry)
|
|||
|
||||
/*
|
||||
* Release the dentry's inode, using the filesystem
|
||||
* d_iput() operation if defined. Dentry has no refcount
|
||||
* and is unhashed.
|
||||
*/
|
||||
static void dentry_iput(struct dentry * dentry)
|
||||
__releases(dentry->d_lock)
|
||||
__releases(dentry->d_inode->i_lock)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
if (inode) {
|
||||
__d_clear_type_and_inode(dentry);
|
||||
hlist_del_init(&dentry->d_u.d_alias);
|
||||
spin_unlock(&dentry->d_lock);
|
||||
spin_unlock(&inode->i_lock);
|
||||
if (!inode->i_nlink)
|
||||
fsnotify_inoderemove(inode);
|
||||
if (dentry->d_op && dentry->d_op->d_iput)
|
||||
dentry->d_op->d_iput(dentry, inode);
|
||||
else
|
||||
iput(inode);
|
||||
} else {
|
||||
spin_unlock(&dentry->d_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the dentry's inode, using the filesystem
|
||||
* d_iput() operation if defined. dentry remains in-use.
|
||||
* d_iput() operation if defined.
|
||||
*/
|
||||
static void dentry_unlink_inode(struct dentry * dentry)
|
||||
__releases(dentry->d_lock)
|
||||
__releases(dentry->d_inode->i_lock)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
bool hashed = !d_unhashed(dentry);
|
||||
|
||||
if (hashed)
|
||||
raw_write_seqcount_begin(&dentry->d_seq);
|
||||
__d_clear_type_and_inode(dentry);
|
||||
hlist_del_init(&dentry->d_u.d_alias);
|
||||
if (hashed)
|
||||
raw_write_seqcount_end(&dentry->d_seq);
|
||||
spin_unlock(&dentry->d_lock);
|
||||
spin_unlock(&inode->i_lock);
|
||||
|
@ -571,12 +547,10 @@ static void __dentry_kill(struct dentry *dentry)
|
|||
dentry_unlist(dentry, parent);
|
||||
if (parent)
|
||||
spin_unlock(&parent->d_lock);
|
||||
dentry_iput(dentry);
|
||||
/*
|
||||
* dentry_iput drops the locks, at which point nobody (except
|
||||
* transient RCU lookups) can reach this dentry.
|
||||
*/
|
||||
BUG_ON(dentry->d_lockref.count > 0);
|
||||
if (dentry->d_inode)
|
||||
dentry_unlink_inode(dentry);
|
||||
else
|
||||
spin_unlock(&dentry->d_lock);
|
||||
this_cpu_dec(nr_dentry);
|
||||
if (dentry->d_op && dentry->d_op->d_release)
|
||||
dentry->d_op->d_release(dentry);
|
||||
|
@ -620,7 +594,6 @@ static struct dentry *dentry_kill(struct dentry *dentry)
|
|||
|
||||
failed:
|
||||
spin_unlock(&dentry->d_lock);
|
||||
cpu_relax();
|
||||
return dentry; /* try again with same dentry */
|
||||
}
|
||||
|
||||
|
@ -794,6 +767,8 @@ void dput(struct dentry *dentry)
|
|||
return;
|
||||
|
||||
repeat:
|
||||
might_sleep();
|
||||
|
||||
rcu_read_lock();
|
||||
if (likely(fast_dput(dentry))) {
|
||||
rcu_read_unlock();
|
||||
|
@ -827,8 +802,10 @@ void dput(struct dentry *dentry)
|
|||
|
||||
kill_it:
|
||||
dentry = dentry_kill(dentry);
|
||||
if (dentry)
|
||||
if (dentry) {
|
||||
cond_resched();
|
||||
goto repeat;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(dput);
|
||||
|
||||
|
@ -1593,6 +1570,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
|
|||
{
|
||||
struct dentry *dentry;
|
||||
char *dname;
|
||||
int err;
|
||||
|
||||
dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);
|
||||
if (!dentry)
|
||||
|
@ -1651,6 +1629,16 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
|
|||
INIT_LIST_HEAD(&dentry->d_child);
|
||||
d_set_d_op(dentry, dentry->d_sb->s_d_op);
|
||||
|
||||
if (dentry->d_op && dentry->d_op->d_init) {
|
||||
err = dentry->d_op->d_init(dentry);
|
||||
if (err) {
|
||||
if (dname_external(dentry))
|
||||
kfree(external_name(dentry));
|
||||
kmem_cache_free(dentry_cache, dentry);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
this_cpu_inc(nr_dentry);
|
||||
|
||||
return dentry;
|
||||
|
@ -1727,7 +1715,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
|
|||
DCACHE_OP_REVALIDATE |
|
||||
DCACHE_OP_WEAK_REVALIDATE |
|
||||
DCACHE_OP_DELETE |
|
||||
DCACHE_OP_SELECT_INODE |
|
||||
DCACHE_OP_REAL));
|
||||
dentry->d_op = op;
|
||||
if (!op)
|
||||
|
@ -1744,8 +1731,6 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
|
|||
dentry->d_flags |= DCACHE_OP_DELETE;
|
||||
if (op->d_prune)
|
||||
dentry->d_flags |= DCACHE_OP_PRUNE;
|
||||
if (op->d_select_inode)
|
||||
dentry->d_flags |= DCACHE_OP_SELECT_INODE;
|
||||
if (op->d_real)
|
||||
dentry->d_flags |= DCACHE_OP_REAL;
|
||||
|
||||
|
@ -1813,7 +1798,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
|
|||
raw_write_seqcount_begin(&dentry->d_seq);
|
||||
__d_set_inode_and_type(dentry, inode, add_flags);
|
||||
raw_write_seqcount_end(&dentry->d_seq);
|
||||
__fsnotify_d_instantiate(dentry);
|
||||
fsnotify_update_flags(dentry);
|
||||
spin_unlock(&dentry->d_lock);
|
||||
}
|
||||
|
||||
|
@ -2065,42 +2050,19 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
|
|||
}
|
||||
EXPORT_SYMBOL(d_add_ci);
|
||||
|
||||
/*
|
||||
* Do the slow-case of the dentry name compare.
|
||||
*
|
||||
* Unlike the dentry_cmp() function, we need to atomically
|
||||
* load the name and length information, so that the
|
||||
* filesystem can rely on them, and can use the 'name' and
|
||||
* 'len' information without worrying about walking off the
|
||||
* end of memory etc.
|
||||
*
|
||||
* Thus the read_seqcount_retry() and the "duplicate" info
|
||||
* in arguments (the low-level filesystem should not look
|
||||
* at the dentry inode or name contents directly, since
|
||||
* rename can change them while we're in RCU mode).
|
||||
*/
|
||||
enum slow_d_compare {
|
||||
D_COMP_OK,
|
||||
D_COMP_NOMATCH,
|
||||
D_COMP_SEQRETRY,
|
||||
};
|
||||
|
||||
static noinline enum slow_d_compare slow_dentry_cmp(
|
||||
static inline bool d_same_name(const struct dentry *dentry,
|
||||
const struct dentry *parent,
|
||||
struct dentry *dentry,
|
||||
unsigned int seq,
|
||||
const struct qstr *name)
|
||||
{
|
||||
int tlen = dentry->d_name.len;
|
||||
const char *tname = dentry->d_name.name;
|
||||
|
||||
if (read_seqcount_retry(&dentry->d_seq, seq)) {
|
||||
cpu_relax();
|
||||
return D_COMP_SEQRETRY;
|
||||
if (likely(!(parent->d_flags & DCACHE_OP_COMPARE))) {
|
||||
if (dentry->d_name.len != name->len)
|
||||
return false;
|
||||
return dentry_cmp(dentry, name->name, name->len) == 0;
|
||||
}
|
||||
if (parent->d_op->d_compare(parent, dentry, tlen, tname, name))
|
||||
return D_COMP_NOMATCH;
|
||||
return D_COMP_OK;
|
||||
return parent->d_op->d_compare(parent, dentry,
|
||||
dentry->d_name.len, dentry->d_name.name,
|
||||
name) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2179,6 +2141,9 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent,
|
|||
* dentry compare, we will do seqretries until it is stable,
|
||||
* and if we end up with a successful lookup, we actually
|
||||
* want to exit RCU lookup anyway.
|
||||
*
|
||||
* Note that raw_seqcount_begin still *does* smp_rmb(), so
|
||||
* we are still guaranteed NUL-termination of ->d_name.name.
|
||||
*/
|
||||
seq = raw_seqcount_begin(&dentry->d_seq);
|
||||
if (dentry->d_parent != parent)
|
||||
|
@ -2187,23 +2152,27 @@ struct dentry *__d_lookup_rcu(const struct dentry *parent,
|
|||
continue;
|
||||
|
||||
if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) {
|
||||
int tlen;
|
||||
const char *tname;
|
||||
if (dentry->d_name.hash != hashlen_hash(hashlen))
|
||||
continue;
|
||||
*seqp = seq;
|
||||
switch (slow_dentry_cmp(parent, dentry, seq, name)) {
|
||||
case D_COMP_OK:
|
||||
return dentry;
|
||||
case D_COMP_NOMATCH:
|
||||
continue;
|
||||
default:
|
||||
tlen = dentry->d_name.len;
|
||||
tname = dentry->d_name.name;
|
||||
/* we want a consistent (name,len) pair */
|
||||
if (read_seqcount_retry(&dentry->d_seq, seq)) {
|
||||
cpu_relax();
|
||||
goto seqretry;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent->d_op->d_compare(parent, dentry,
|
||||
tlen, tname, name) != 0)
|
||||
continue;
|
||||
} else {
|
||||
if (dentry->d_name.hash_len != hashlen)
|
||||
continue;
|
||||
if (dentry_cmp(dentry, str, hashlen_len(hashlen)) != 0)
|
||||
continue;
|
||||
}
|
||||
*seqp = seq;
|
||||
if (!dentry_cmp(dentry, str, hashlen_len(hashlen)))
|
||||
return dentry;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -2252,9 +2221,7 @@ EXPORT_SYMBOL(d_lookup);
|
|||
*/
|
||||
struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
|
||||
{
|
||||
unsigned int len = name->len;
|
||||
unsigned int hash = name->hash;
|
||||
const unsigned char *str = name->name;
|
||||
struct hlist_bl_head *b = d_hash(hash);
|
||||
struct hlist_bl_node *node;
|
||||
struct dentry *found = NULL;
|
||||
|
@ -2293,21 +2260,8 @@ struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
|
|||
if (d_unhashed(dentry))
|
||||
goto next;
|
||||
|
||||
/*
|
||||
* It is safe to compare names since d_move() cannot
|
||||
* change the qstr (protected by d_lock).
|
||||
*/
|
||||
if (parent->d_flags & DCACHE_OP_COMPARE) {
|
||||
int tlen = dentry->d_name.len;
|
||||
const char *tname = dentry->d_name.name;
|
||||
if (parent->d_op->d_compare(parent, dentry, tlen, tname, name))
|
||||
if (!d_same_name(dentry, parent, name))
|
||||
goto next;
|
||||
} else {
|
||||
if (dentry->d_name.len != len)
|
||||
goto next;
|
||||
if (dentry_cmp(dentry, str, len))
|
||||
goto next;
|
||||
}
|
||||
|
||||
dentry->d_lockref.count++;
|
||||
found = dentry;
|
||||
|
@ -2460,9 +2414,7 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
|
|||
const struct qstr *name,
|
||||
wait_queue_head_t *wq)
|
||||
{
|
||||
unsigned int len = name->len;
|
||||
unsigned int hash = name->hash;
|
||||
const unsigned char *str = name->name;
|
||||
struct hlist_bl_head *b = in_lookup_hash(parent, hash);
|
||||
struct hlist_bl_node *node;
|
||||
struct dentry *new = d_alloc(parent, name);
|
||||
|
@ -2513,17 +2465,8 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
|
|||
continue;
|
||||
if (dentry->d_parent != parent)
|
||||
continue;
|
||||
if (parent->d_flags & DCACHE_OP_COMPARE) {
|
||||
int tlen = dentry->d_name.len;
|
||||
const char *tname = dentry->d_name.name;
|
||||
if (parent->d_op->d_compare(parent, dentry, tlen, tname, name))
|
||||
if (!d_same_name(dentry, parent, name))
|
||||
continue;
|
||||
} else {
|
||||
if (dentry->d_name.len != len)
|
||||
continue;
|
||||
if (dentry_cmp(dentry, str, len))
|
||||
continue;
|
||||
}
|
||||
hlist_bl_unlock(b);
|
||||
/* now we can try to grab a reference */
|
||||
if (!lockref_get_not_dead(&dentry->d_lockref)) {
|
||||
|
@ -2550,17 +2493,8 @@ struct dentry *d_alloc_parallel(struct dentry *parent,
|
|||
goto mismatch;
|
||||
if (unlikely(d_unhashed(dentry)))
|
||||
goto mismatch;
|
||||
if (parent->d_flags & DCACHE_OP_COMPARE) {
|
||||
int tlen = dentry->d_name.len;
|
||||
const char *tname = dentry->d_name.name;
|
||||
if (parent->d_op->d_compare(parent, dentry, tlen, tname, name))
|
||||
if (unlikely(!d_same_name(dentry, parent, name)))
|
||||
goto mismatch;
|
||||
} else {
|
||||
if (unlikely(dentry->d_name.len != len))
|
||||
goto mismatch;
|
||||
if (unlikely(dentry_cmp(dentry, str, len)))
|
||||
goto mismatch;
|
||||
}
|
||||
/* OK, it *is* a hashed match; return it */
|
||||
spin_unlock(&dentry->d_lock);
|
||||
dput(new);
|
||||
|
@ -2613,7 +2547,7 @@ static inline void __d_add(struct dentry *dentry, struct inode *inode)
|
|||
raw_write_seqcount_begin(&dentry->d_seq);
|
||||
__d_set_inode_and_type(dentry, inode, add_flags);
|
||||
raw_write_seqcount_end(&dentry->d_seq);
|
||||
__fsnotify_d_instantiate(dentry);
|
||||
fsnotify_update_flags(dentry);
|
||||
}
|
||||
_d_rehash(dentry);
|
||||
if (dir)
|
||||
|
@ -2656,8 +2590,6 @@ EXPORT_SYMBOL(d_add);
|
|||
struct dentry *d_exact_alias(struct dentry *entry, struct inode *inode)
|
||||
{
|
||||
struct dentry *alias;
|
||||
int len = entry->d_name.len;
|
||||
const char *name = entry->d_name.name;
|
||||
unsigned int hash = entry->d_name.hash;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
|
@ -2671,9 +2603,7 @@ struct dentry *d_exact_alias(struct dentry *entry, struct inode *inode)
|
|||
continue;
|
||||
if (alias->d_parent != entry->d_parent)
|
||||
continue;
|
||||
if (alias->d_name.len != len)
|
||||
continue;
|
||||
if (dentry_cmp(alias, name, len))
|
||||
if (!d_same_name(alias, entry->d_parent, &entry->d_name))
|
||||
continue;
|
||||
spin_lock(&alias->d_lock);
|
||||
if (!d_unhashed(alias)) {
|
||||
|
@ -2903,8 +2833,8 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
|
|||
list_move(&target->d_child, &target->d_parent->d_subdirs);
|
||||
list_move(&dentry->d_child, &dentry->d_parent->d_subdirs);
|
||||
if (exchange)
|
||||
fsnotify_d_move(target);
|
||||
fsnotify_d_move(dentry);
|
||||
fsnotify_update_flags(target);
|
||||
fsnotify_update_flags(dentry);
|
||||
}
|
||||
|
||||
write_seqcount_end(&target->d_seq);
|
||||
|
|
|
@ -621,9 +621,6 @@ void debugfs_remove(struct dentry *dentry)
|
|||
return;
|
||||
|
||||
parent = dentry->d_parent;
|
||||
if (!parent || d_really_is_negative(parent))
|
||||
return;
|
||||
|
||||
inode_lock(d_inode(parent));
|
||||
ret = __debugfs_remove(dentry, parent);
|
||||
inode_unlock(d_inode(parent));
|
||||
|
@ -654,10 +651,6 @@ void debugfs_remove_recursive(struct dentry *dentry)
|
|||
if (IS_ERR_OR_NULL(dentry))
|
||||
return;
|
||||
|
||||
parent = dentry->d_parent;
|
||||
if (!parent || d_really_is_negative(parent))
|
||||
return;
|
||||
|
||||
parent = dentry;
|
||||
down:
|
||||
inode_lock(d_inode(parent));
|
||||
|
|
|
@ -2350,7 +2350,6 @@ static int ext4_mb_seq_groups_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
const struct file_operations ext4_seq_mb_groups_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = ext4_mb_seq_groups_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -359,7 +359,6 @@ static int name##_open(struct inode *inode, struct file *file) \
|
|||
} \
|
||||
\
|
||||
static const struct file_operations ext4_seq_##name##_fops = { \
|
||||
.owner = THIS_MODULE, \
|
||||
.open = name##_open, \
|
||||
.read = seq_read, \
|
||||
.llseek = seq_lseek, \
|
||||
|
|
|
@ -961,7 +961,6 @@ static int _name##_open_fs(struct inode *inode, struct file *file) \
|
|||
} \
|
||||
\
|
||||
static const struct file_operations f2fs_seq_##_name##_fops = { \
|
||||
.owner = THIS_MODULE, \
|
||||
.open = _name##_open_fs, \
|
||||
.read = seq_read, \
|
||||
.llseek = seq_lseek, \
|
||||
|
|
|
@ -99,7 +99,6 @@ static int fscache_histogram_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
const struct file_operations fscache_histogram_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = fscache_histogram_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -404,7 +404,6 @@ static int fscache_objlist_release(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
const struct file_operations fscache_objlist_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = fscache_objlist_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -295,7 +295,6 @@ static int fscache_stats_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
const struct file_operations fscache_stats_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = fscache_stats_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -128,7 +128,7 @@ static ssize_t hfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
|||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct address_space *mapping = file->f_mapping;
|
||||
struct inode *inode = file_inode(file)->i_mapping->host;
|
||||
struct inode *inode = mapping->host;
|
||||
size_t count = iov_iter_count(iter);
|
||||
ssize_t ret;
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ static ssize_t hfsplus_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
|||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct address_space *mapping = file->f_mapping;
|
||||
struct inode *inode = file_inode(file)->i_mapping->host;
|
||||
struct inode *inode = mapping->host;
|
||||
size_t count = iov_iter_count(iter);
|
||||
ssize_t ret;
|
||||
|
||||
|
|
|
@ -361,7 +361,6 @@ static int zisofs_readpage(struct file *file, struct page *page)
|
|||
|
||||
const struct address_space_operations zisofs_aops = {
|
||||
.readpage = zisofs_readpage,
|
||||
/* No sync_page operation supported? */
|
||||
/* No bmap operation supported */
|
||||
};
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ static ssize_t jfs_loglevel_proc_write(struct file *file,
|
|||
}
|
||||
|
||||
static const struct file_operations jfs_loglevel_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = jfs_loglevel_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -2517,7 +2517,6 @@ static int jfs_lmstats_proc_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
const struct file_operations jfs_lmstats_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = jfs_lmstats_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -830,7 +830,6 @@ static int jfs_mpstat_proc_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
const struct file_operations jfs_mpstat_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = jfs_mpstat_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -3040,7 +3040,6 @@ static int jfs_txanchor_proc_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
const struct file_operations jfs_txanchor_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = jfs_txanchor_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
@ -3081,7 +3080,6 @@ static int jfs_txstats_proc_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
const struct file_operations jfs_txstats_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = jfs_txstats_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -3894,7 +3894,6 @@ static int jfs_xtstat_proc_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
const struct file_operations jfs_xtstat_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = jfs_xtstat_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -64,7 +64,6 @@ static const struct file_operations lockd_end_grace_operations = {
|
|||
.read = nlm_end_grace_read,
|
||||
.llseek = default_llseek,
|
||||
.release = simple_transaction_release,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
int __init
|
||||
|
|
|
@ -1449,9 +1449,8 @@ static int follow_dotdot(struct nameidata *nd)
|
|||
}
|
||||
|
||||
/*
|
||||
* This looks up the name in dcache, possibly revalidates the old dentry and
|
||||
* allocates a new one if not found or not valid. In the need_lookup argument
|
||||
* returns whether i_op->lookup is necessary.
|
||||
* This looks up the name in dcache and possibly revalidates the found dentry.
|
||||
* NULL is returned if the dentry does not exist in the cache.
|
||||
*/
|
||||
static struct dentry *lookup_dcache(const struct qstr *name,
|
||||
struct dentry *dir,
|
||||
|
@ -4336,7 +4335,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
* Check source == target.
|
||||
* On overlayfs need to look at underlying inodes.
|
||||
*/
|
||||
if (vfs_select_inode(old_dentry, 0) == vfs_select_inode(new_dentry, 0))
|
||||
if (d_real_inode(old_dentry) == d_real_inode(new_dentry))
|
||||
return 0;
|
||||
|
||||
error = may_delete(old_dir, old_dentry, is_dir);
|
||||
|
|
|
@ -1102,7 +1102,6 @@ static const struct file_operations nfs_server_list_fops = {
|
|||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release_net,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int nfs_volume_list_open(struct inode *inode, struct file *file);
|
||||
|
@ -1123,7 +1122,6 @@ static const struct file_operations nfs_volume_list_fops = {
|
|||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release_net,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
11
fs/nfs/dir.c
11
fs/nfs/dir.c
|
@ -734,7 +734,7 @@ struct page *get_cache_page(nfs_readdir_descriptor_t *desc)
|
|||
struct page *page;
|
||||
|
||||
for (;;) {
|
||||
page = read_cache_page(file_inode(desc->file)->i_mapping,
|
||||
page = read_cache_page(desc->file->f_mapping,
|
||||
desc->page_index, (filler_t *)nfs_readdir_filler, desc);
|
||||
if (IS_ERR(page) || grab_page(page))
|
||||
break;
|
||||
|
@ -1397,19 +1397,18 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
|
|||
if (IS_ERR(label))
|
||||
goto out;
|
||||
|
||||
/* Protect against concurrent sillydeletes */
|
||||
trace_nfs_lookup_enter(dir, dentry, flags);
|
||||
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
|
||||
if (error == -ENOENT)
|
||||
goto no_entry;
|
||||
if (error < 0) {
|
||||
res = ERR_PTR(error);
|
||||
goto out_unblock_sillyrename;
|
||||
goto out_label;
|
||||
}
|
||||
inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label);
|
||||
res = ERR_CAST(inode);
|
||||
if (IS_ERR(res))
|
||||
goto out_unblock_sillyrename;
|
||||
goto out_label;
|
||||
|
||||
/* Success: notify readdir to use READDIRPLUS */
|
||||
nfs_advise_use_readdirplus(dir);
|
||||
|
@ -1418,11 +1417,11 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
|
|||
res = d_splice_alias(inode, dentry);
|
||||
if (res != NULL) {
|
||||
if (IS_ERR(res))
|
||||
goto out_unblock_sillyrename;
|
||||
goto out_label;
|
||||
dentry = res;
|
||||
}
|
||||
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
||||
out_unblock_sillyrename:
|
||||
out_label:
|
||||
trace_nfs_lookup_exit(dir, dentry, flags, error);
|
||||
nfs4_label_free(label);
|
||||
out:
|
||||
|
|
|
@ -244,9 +244,7 @@ static int nfs_direct_cmp_commit_data_verf(struct nfs_direct_req *dreq,
|
|||
/**
|
||||
* nfs_direct_IO - NFS address space operation for direct I/O
|
||||
* @iocb: target I/O control block
|
||||
* @iov: array of vectors that define I/O buffer
|
||||
* @pos: offset in file to begin the operation
|
||||
* @nr_segs: size of iovec array
|
||||
* @iter: I/O buffer
|
||||
*
|
||||
* The presence of this routine in the address space ops vector means
|
||||
* the NFS client supports direct I/O. However, for most direct IO, we
|
||||
|
|
|
@ -158,7 +158,6 @@ static const struct file_operations exports_proc_operations = {
|
|||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int exports_nfsd_open(struct inode *inode, struct file *file)
|
||||
|
@ -171,7 +170,6 @@ static const struct file_operations exports_nfsd_operations = {
|
|||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int export_features_show(struct seq_file *m, void *v)
|
||||
|
@ -217,7 +215,6 @@ static const struct file_operations pool_stats_operations = {
|
|||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = nfsd_pool_stats_release,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct file_operations reply_cache_stats_operations = {
|
||||
|
|
|
@ -84,7 +84,6 @@ static int nfsd_proc_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
static const struct file_operations nfsd_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = nfsd_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -1854,7 +1854,7 @@ int ntfs_read_inode_mount(struct inode *vi)
|
|||
/* Need this to sanity check attribute list references to $MFT. */
|
||||
vi->i_generation = ni->seq_no = le16_to_cpu(m->sequence_number);
|
||||
|
||||
/* Provides readpage() and sync_page() for map_mft_record(). */
|
||||
/* Provides readpage() for map_mft_record(). */
|
||||
vi->i_mapping->a_ops = &ntfs_mst_aops;
|
||||
|
||||
ctx = ntfs_attr_get_search_ctx(ni, m);
|
||||
|
|
|
@ -2426,7 +2426,7 @@ static int ocfs2_dio_end_io(struct kiocb *iocb,
|
|||
static ssize_t ocfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file_inode(file)->i_mapping->host;
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||
get_block_t *get_block;
|
||||
|
||||
|
|
|
@ -840,13 +840,13 @@ EXPORT_SYMBOL(file_path);
|
|||
int vfs_open(const struct path *path, struct file *file,
|
||||
const struct cred *cred)
|
||||
{
|
||||
struct inode *inode = vfs_select_inode(path->dentry, file->f_flags);
|
||||
struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags);
|
||||
|
||||
if (IS_ERR(inode))
|
||||
return PTR_ERR(inode);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
file->f_path = *path;
|
||||
return do_dentry_open(file, inode, NULL, cred);
|
||||
return do_dentry_open(file, d_backing_inode(dentry), NULL, cred);
|
||||
}
|
||||
|
||||
struct file *dentry_open(const struct path *path, int flags,
|
||||
|
|
|
@ -291,7 +291,7 @@ int orangefs_permission(struct inode *inode, int mask)
|
|||
}
|
||||
|
||||
/* ORANGEDS2 implementation of VFS inode operations for files */
|
||||
struct inode_operations orangefs_file_inode_operations = {
|
||||
const struct inode_operations orangefs_file_inode_operations = {
|
||||
.get_acl = orangefs_get_acl,
|
||||
.set_acl = orangefs_set_acl,
|
||||
.setattr = orangefs_setattr,
|
||||
|
|
|
@ -405,12 +405,8 @@ static int orangefs_rename(struct inode *old_dir,
|
|||
int ret;
|
||||
|
||||
gossip_debug(GOSSIP_NAME_DEBUG,
|
||||
"orangefs_rename: called (%s/%s => %s/%s) ct=%d\n",
|
||||
old_dentry->d_parent->d_name.name,
|
||||
old_dentry->d_name.name,
|
||||
new_dentry->d_parent->d_name.name,
|
||||
new_dentry->d_name.name,
|
||||
d_count(new_dentry));
|
||||
"orangefs_rename: called (%pd2 => %pd2) ct=%d\n",
|
||||
old_dentry, new_dentry, d_count(new_dentry));
|
||||
|
||||
new_op = op_alloc(ORANGEFS_VFS_OP_RENAME);
|
||||
if (!new_op)
|
||||
|
@ -442,7 +438,7 @@ static int orangefs_rename(struct inode *old_dir,
|
|||
}
|
||||
|
||||
/* ORANGEFS implementation of VFS inode operations for directories */
|
||||
struct inode_operations orangefs_dir_inode_operations = {
|
||||
const struct inode_operations orangefs_dir_inode_operations = {
|
||||
.lookup = orangefs_lookup,
|
||||
.get_acl = orangefs_get_acl,
|
||||
.set_acl = orangefs_set_acl,
|
||||
|
|
|
@ -557,10 +557,10 @@ extern int hash_table_size;
|
|||
|
||||
extern const struct address_space_operations orangefs_address_operations;
|
||||
extern struct backing_dev_info orangefs_backing_dev_info;
|
||||
extern struct inode_operations orangefs_file_inode_operations;
|
||||
extern const struct inode_operations orangefs_file_inode_operations;
|
||||
extern const struct file_operations orangefs_file_operations;
|
||||
extern struct inode_operations orangefs_symlink_inode_operations;
|
||||
extern struct inode_operations orangefs_dir_inode_operations;
|
||||
extern const struct inode_operations orangefs_symlink_inode_operations;
|
||||
extern const struct inode_operations orangefs_dir_inode_operations;
|
||||
extern const struct file_operations orangefs_dir_operations;
|
||||
extern const struct dentry_operations orangefs_dentry_operations;
|
||||
extern const struct file_operations orangefs_devreq_file_operations;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "orangefs-kernel.h"
|
||||
#include "orangefs-bufmap.h"
|
||||
|
||||
struct inode_operations orangefs_symlink_inode_operations = {
|
||||
const struct inode_operations orangefs_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = simple_get_link,
|
||||
.setattr = orangefs_setattr,
|
||||
|
|
|
@ -351,36 +351,25 @@ static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
|
|||
return true;
|
||||
}
|
||||
|
||||
struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags)
|
||||
int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
struct path realpath;
|
||||
enum ovl_path_type type;
|
||||
|
||||
if (d_is_dir(dentry))
|
||||
return d_backing_inode(dentry);
|
||||
|
||||
type = ovl_path_real(dentry, &realpath);
|
||||
if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) {
|
||||
err = ovl_want_write(dentry);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
if (!err) {
|
||||
if (file_flags & O_TRUNC)
|
||||
err = ovl_copy_up_truncate(dentry);
|
||||
else
|
||||
err = ovl_copy_up(dentry);
|
||||
ovl_drop_write(dentry);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
ovl_path_upper(dentry, &realpath);
|
||||
}
|
||||
}
|
||||
|
||||
if (realpath.dentry->d_flags & DCACHE_OP_SELECT_INODE)
|
||||
return realpath.dentry->d_op->d_select_inode(realpath.dentry, file_flags);
|
||||
|
||||
return d_backing_inode(realpath.dentry);
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct inode_operations ovl_file_inode_operations = {
|
||||
|
|
|
@ -179,7 +179,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
|
|||
const char *name, void *value, size_t size);
|
||||
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
|
||||
int ovl_removexattr(struct dentry *dentry, const char *name);
|
||||
struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags);
|
||||
int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags);
|
||||
|
||||
struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
|
||||
struct ovl_entry *oe);
|
||||
|
|
|
@ -304,7 +304,9 @@ static void ovl_dentry_release(struct dentry *dentry)
|
|||
}
|
||||
}
|
||||
|
||||
static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode)
|
||||
static struct dentry *ovl_d_real(struct dentry *dentry,
|
||||
const struct inode *inode,
|
||||
unsigned int open_flags)
|
||||
{
|
||||
struct dentry *real;
|
||||
|
||||
|
@ -314,6 +316,16 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode)
|
|||
goto bug;
|
||||
}
|
||||
|
||||
if (d_is_negative(dentry))
|
||||
return dentry;
|
||||
|
||||
if (open_flags) {
|
||||
int err = ovl_open_maybe_copy_up(dentry, open_flags);
|
||||
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
real = ovl_dentry_upper(dentry);
|
||||
if (real && (!inode || inode == d_inode(real)))
|
||||
return real;
|
||||
|
@ -326,9 +338,7 @@ static struct dentry *ovl_d_real(struct dentry *dentry, struct inode *inode)
|
|||
return real;
|
||||
|
||||
/* Handle recursion */
|
||||
if (real->d_flags & DCACHE_OP_REAL)
|
||||
return real->d_op->d_real(real, inode);
|
||||
|
||||
return d_real(real, inode, open_flags);
|
||||
bug:
|
||||
WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry,
|
||||
inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0);
|
||||
|
@ -378,13 +388,11 @@ static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
|
|||
|
||||
static const struct dentry_operations ovl_dentry_operations = {
|
||||
.d_release = ovl_dentry_release,
|
||||
.d_select_inode = ovl_d_select_inode,
|
||||
.d_real = ovl_d_real,
|
||||
};
|
||||
|
||||
static const struct dentry_operations ovl_reval_dentry_operations = {
|
||||
.d_release = ovl_dentry_release,
|
||||
.d_select_inode = ovl_d_select_inode,
|
||||
.d_real = ovl_d_real,
|
||||
.d_revalidate = ovl_dentry_revalidate,
|
||||
.d_weak_revalidate = ovl_dentry_weak_revalidate,
|
||||
|
|
|
@ -541,9 +541,6 @@ void tracefs_remove(struct dentry *dentry)
|
|||
return;
|
||||
|
||||
parent = dentry->d_parent;
|
||||
if (!parent || !parent->d_inode)
|
||||
return;
|
||||
|
||||
inode_lock(parent->d_inode);
|
||||
ret = __tracefs_remove(dentry, parent);
|
||||
inode_unlock(parent->d_inode);
|
||||
|
@ -566,10 +563,6 @@ void tracefs_remove_recursive(struct dentry *dentry)
|
|||
if (IS_ERR_OR_NULL(dentry))
|
||||
return;
|
||||
|
||||
parent = dentry->d_parent;
|
||||
if (!parent || !parent->d_inode)
|
||||
return;
|
||||
|
||||
parent = dentry;
|
||||
down:
|
||||
inode_lock(parent->d_inode);
|
||||
|
|
17
fs/ufs/dir.c
17
fs/ufs/dir.c
|
@ -279,12 +279,6 @@ struct ufs_dir_entry *ufs_find_entry(struct inode *dir, const struct qstr *qstr,
|
|||
de = (struct ufs_dir_entry *) kaddr;
|
||||
kaddr += ufs_last_byte(dir, n) - reclen;
|
||||
while ((char *) de <= kaddr) {
|
||||
if (de->d_reclen == 0) {
|
||||
ufs_error(dir->i_sb, __func__,
|
||||
"zero-length directory entry");
|
||||
ufs_put_page(page);
|
||||
goto out;
|
||||
}
|
||||
if (ufs_match(sb, namelen, name, de))
|
||||
goto found;
|
||||
de = ufs_next_entry(sb, de);
|
||||
|
@ -414,11 +408,8 @@ ufs_validate_entry(struct super_block *sb, char *base,
|
|||
{
|
||||
struct ufs_dir_entry *de = (struct ufs_dir_entry*)(base + offset);
|
||||
struct ufs_dir_entry *p = (struct ufs_dir_entry*)(base + (offset&mask));
|
||||
while ((char*)p < (char*)de) {
|
||||
if (p->d_reclen == 0)
|
||||
break;
|
||||
while ((char*)p < (char*)de)
|
||||
p = ufs_next_entry(sb, p);
|
||||
}
|
||||
return (char *)p - base;
|
||||
}
|
||||
|
||||
|
@ -469,12 +460,6 @@ ufs_readdir(struct file *file, struct dir_context *ctx)
|
|||
de = (struct ufs_dir_entry *)(kaddr+offset);
|
||||
limit = kaddr + ufs_last_byte(inode, n) - UFS_DIR_REC_LEN(1);
|
||||
for ( ;(char*)de <= limit; de = ufs_next_entry(sb, de)) {
|
||||
if (de->d_reclen == 0) {
|
||||
ufs_error(sb, __func__,
|
||||
"zero-length directory entry");
|
||||
ufs_put_page(page);
|
||||
return -EIO;
|
||||
}
|
||||
if (de->d_ino) {
|
||||
unsigned char d_type = DT_UNKNOWN;
|
||||
|
||||
|
|
|
@ -128,7 +128,6 @@ static int xqm_proc_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
static const struct file_operations xqm_proc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = xqm_proc_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
|
|
|
@ -133,14 +133,15 @@ 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_prune)(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 inode *(*d_select_inode)(struct dentry *, unsigned);
|
||||
struct dentry *(*d_real)(struct dentry *, struct inode *);
|
||||
struct dentry *(*d_real)(struct dentry *, const struct inode *,
|
||||
unsigned int);
|
||||
} ____cacheline_aligned;
|
||||
|
||||
/*
|
||||
|
@ -206,10 +207,8 @@ struct dentry_operations {
|
|||
|
||||
#define DCACHE_MAY_FREE 0x00800000
|
||||
#define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */
|
||||
#define DCACHE_OP_SELECT_INODE 0x02000000 /* Unioned entry: dcache op selects inode */
|
||||
|
||||
#define DCACHE_ENCRYPTED_WITH_KEY 0x04000000 /* dir is encrypted with a valid key */
|
||||
#define DCACHE_OP_REAL 0x08000000
|
||||
#define DCACHE_ENCRYPTED_WITH_KEY 0x02000000 /* dir is encrypted with a valid key */
|
||||
#define DCACHE_OP_REAL 0x04000000
|
||||
|
||||
#define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */
|
||||
#define DCACHE_DENTRY_CURSOR 0x20000000
|
||||
|
@ -557,25 +556,27 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper)
|
|||
return upper;
|
||||
}
|
||||
|
||||
static inline struct dentry *d_real(struct dentry *dentry)
|
||||
/**
|
||||
* d_real - Return the real dentry
|
||||
* @dentry: the dentry to query
|
||||
* @inode: inode to select the dentry from multiple layers (can be NULL)
|
||||
* @flags: open flags to control copy-up behavior
|
||||
*
|
||||
* If dentry is on an union/overlay, then return the underlying, real dentry.
|
||||
* Otherwise return the dentry itself.
|
||||
*
|
||||
* See also: Documentation/filesystems/vfs.txt
|
||||
*/
|
||||
static inline struct dentry *d_real(struct dentry *dentry,
|
||||
const struct inode *inode,
|
||||
unsigned int flags)
|
||||
{
|
||||
if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
|
||||
return dentry->d_op->d_real(dentry, NULL);
|
||||
return dentry->d_op->d_real(dentry, inode, flags);
|
||||
else
|
||||
return dentry;
|
||||
}
|
||||
|
||||
static inline struct inode *vfs_select_inode(struct dentry *dentry,
|
||||
unsigned open_flags)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
if (inode && unlikely(dentry->d_flags & DCACHE_OP_SELECT_INODE))
|
||||
inode = dentry->d_op->d_select_inode(dentry, open_flags);
|
||||
|
||||
return inode;
|
||||
}
|
||||
|
||||
/**
|
||||
* d_real_inode - Return the real inode
|
||||
* @dentry: The dentry to query
|
||||
|
@ -585,7 +586,7 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry,
|
|||
*/
|
||||
static inline struct inode *d_real_inode(struct dentry *dentry)
|
||||
{
|
||||
return d_backing_inode(d_real(dentry));
|
||||
return d_backing_inode(d_real(dentry, NULL, 0));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -457,7 +457,6 @@ struct block_device {
|
|||
struct inode * bd_inode; /* will die */
|
||||
struct super_block * bd_super;
|
||||
struct mutex bd_mutex; /* open/close mutex */
|
||||
struct list_head bd_inodes;
|
||||
void * bd_claiming;
|
||||
void * bd_holder;
|
||||
int bd_holders;
|
||||
|
@ -1271,12 +1270,7 @@ static inline struct inode *file_inode(const struct file *f)
|
|||
|
||||
static inline struct dentry *file_dentry(const struct file *file)
|
||||
{
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
|
||||
if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
|
||||
return dentry->d_op->d_real(dentry, file_inode(file));
|
||||
else
|
||||
return dentry;
|
||||
return d_real(file->f_path.dentry, file_inode(file), 0);
|
||||
}
|
||||
|
||||
static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl)
|
||||
|
|
|
@ -51,18 +51,6 @@ static inline int fsnotify_perm(struct file *file, int mask)
|
|||
return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* fsnotify_d_move - dentry has been moved
|
||||
*/
|
||||
static inline void fsnotify_d_move(struct dentry *dentry)
|
||||
{
|
||||
/*
|
||||
* On move we need to update dentry->d_flags to indicate if the new parent
|
||||
* cares about events from this dentry.
|
||||
*/
|
||||
__fsnotify_update_dcache_flags(dentry);
|
||||
}
|
||||
|
||||
/*
|
||||
* fsnotify_link_count - inode's link count changed
|
||||
*/
|
||||
|
|
|
@ -267,10 +267,8 @@ static inline int fsnotify_inode_watches_children(struct inode *inode)
|
|||
* Update the dentry with a flag indicating the interest of its parent to receive
|
||||
* filesystem events when those events happens to this dentry->d_inode.
|
||||
*/
|
||||
static inline void __fsnotify_update_dcache_flags(struct dentry *dentry)
|
||||
static inline void fsnotify_update_flags(struct dentry *dentry)
|
||||
{
|
||||
struct dentry *parent;
|
||||
|
||||
assert_spin_locked(&dentry->d_lock);
|
||||
|
||||
/*
|
||||
|
@ -280,21 +278,12 @@ static inline void __fsnotify_update_dcache_flags(struct dentry *dentry)
|
|||
* find our entry, so it will spin until we complete here, and update
|
||||
* us with the new state.
|
||||
*/
|
||||
parent = dentry->d_parent;
|
||||
if (parent->d_inode && fsnotify_inode_watches_children(parent->d_inode))
|
||||
if (fsnotify_inode_watches_children(dentry->d_parent->d_inode))
|
||||
dentry->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED;
|
||||
else
|
||||
dentry->d_flags &= ~DCACHE_FSNOTIFY_PARENT_WATCHED;
|
||||
}
|
||||
|
||||
/*
|
||||
* fsnotify_d_instantiate - instantiate a dentry for inode
|
||||
*/
|
||||
static inline void __fsnotify_d_instantiate(struct dentry *dentry)
|
||||
{
|
||||
__fsnotify_update_dcache_flags(dentry);
|
||||
}
|
||||
|
||||
/* called from fsnotify listeners, such as fanotify or dnotify */
|
||||
|
||||
/* create a new group */
|
||||
|
@ -386,10 +375,7 @@ static inline void __fsnotify_inode_delete(struct inode *inode)
|
|||
static inline void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
|
||||
{}
|
||||
|
||||
static inline void __fsnotify_update_dcache_flags(struct dentry *dentry)
|
||||
{}
|
||||
|
||||
static inline void __fsnotify_d_instantiate(struct dentry *dentry)
|
||||
static inline void fsnotify_update_flags(struct dentry *dentry)
|
||||
{}
|
||||
|
||||
static inline u32 fsnotify_get_cookie(void)
|
||||
|
|
|
@ -3316,7 +3316,7 @@ static void unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,
|
|||
address = address & huge_page_mask(h);
|
||||
pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) +
|
||||
vma->vm_pgoff;
|
||||
mapping = file_inode(vma->vm_file)->i_mapping;
|
||||
mapping = vma->vm_file->f_mapping;
|
||||
|
||||
/*
|
||||
* Take the mapping lock for the duration of the table walk. As
|
||||
|
|
|
@ -186,24 +186,21 @@ EXPORT_SYMBOL_GPL(securityfs_create_dir);
|
|||
*/
|
||||
void securityfs_remove(struct dentry *dentry)
|
||||
{
|
||||
struct dentry *parent;
|
||||
struct inode *dir;
|
||||
|
||||
if (!dentry || IS_ERR(dentry))
|
||||
return;
|
||||
|
||||
parent = dentry->d_parent;
|
||||
if (!parent || d_really_is_negative(parent))
|
||||
return;
|
||||
|
||||
inode_lock(d_inode(parent));
|
||||
dir = d_inode(dentry->d_parent);
|
||||
inode_lock(dir);
|
||||
if (simple_positive(dentry)) {
|
||||
if (d_is_dir(dentry))
|
||||
simple_rmdir(d_inode(parent), dentry);
|
||||
simple_rmdir(dir, dentry);
|
||||
else
|
||||
simple_unlink(d_inode(parent), dentry);
|
||||
simple_unlink(dir, dentry);
|
||||
dput(dentry);
|
||||
}
|
||||
inode_unlock(d_inode(parent));
|
||||
inode_unlock(dir);
|
||||
simple_release_fs(&mount, &mount_count);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(securityfs_remove);
|
||||
|
|
Loading…
Reference in a new issue