Skip to content

Commit

Permalink
Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  ...
  • Loading branch information
torvalds committed Jul 28, 2016
2 parents 554828e + 47be618 commit 6784725
Show file tree
Hide file tree
Showing 61 changed files with 224 additions and 413 deletions.
3 changes: 1 addition & 2 deletions Documentation/block/biodoc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 7 additions & 11 deletions Documentation/filesystems/Locking
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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:
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down
51 changes: 32 additions & 19 deletions Documentation/filesystems/vfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 0 additions & 4 deletions drivers/block/drbd/drbd_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/armada/armada_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/drm_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/etnaviv/etnaviv_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
10 changes: 5 additions & 5 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/omapdrm/omap_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/ttm/ttm_tt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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];
Expand Down
4 changes: 4 additions & 0 deletions fs/9p/fid.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 0 additions & 1 deletion fs/9p/vfs_addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 5 additions & 5 deletions fs/9p/vfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 6784725

Please sign in to comment.