Skip to content

Commit

Permalink
Merge branch 'work.icache' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/viro/vfs

Pull vfs inode freeing updates from Al Viro:
 "Introduction of separate method for RCU-delayed part of
  ->destroy_inode() (if any).

  Pretty much as posted, except that destroy_inode() stashes
  ->free_inode into the victim (anon-unioned with ->i_fops) before
  scheduling i_callback() and the last two patches (sockfs conversion
  and folding struct socket_wq into struct socket) are excluded - that
  pair should go through netdev once davem reopens his tree"

* 'work.icache' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (58 commits)
  orangefs: make use of ->free_inode()
  shmem: make use of ->free_inode()
  hugetlb: make use of ->free_inode()
  overlayfs: make use of ->free_inode()
  jfs: switch to ->free_inode()
  fuse: switch to ->free_inode()
  ext4: make use of ->free_inode()
  ecryptfs: make use of ->free_inode()
  ceph: use ->free_inode()
  btrfs: use ->free_inode()
  afs: switch to use of ->free_inode()
  dax: make use of ->free_inode()
  ntfs: switch to ->free_inode()
  securityfs: switch to ->free_inode()
  apparmor: switch to ->free_inode()
  rpcpipe: switch to ->free_inode()
  bpf: switch to ->free_inode()
  mqueue: switch to ->free_inode()
  ufs: switch to ->free_inode()
  coda: switch to ->free_inode()
  ...
  • Loading branch information
torvalds committed May 7, 2019
2 parents 8ff468c + f276ae0 commit 168e153
Show file tree
Hide file tree
Showing 74 changed files with 230 additions and 493 deletions.
2 changes: 2 additions & 0 deletions Documentation/filesystems/Locking
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ set: exclusive
--------------------------- super_operations ---------------------------
prototypes:
struct inode *(*alloc_inode)(struct super_block *sb);
void (*free_inode)(struct inode *);
void (*destroy_inode)(struct inode *);
void (*dirty_inode) (struct inode *, int flags);
int (*write_inode) (struct inode *, struct writeback_control *wbc);
Expand All @@ -139,6 +140,7 @@ locking rules:
All may block [not true, see below]
s_umount
alloc_inode:
free_inode: called from RCU callback
destroy_inode:
dirty_inode:
write_inode:
Expand Down
25 changes: 25 additions & 0 deletions Documentation/filesystems/porting
Original file line number Diff line number Diff line change
Expand Up @@ -638,3 +638,28 @@ in your dentry operations instead.
inode to d_splice_alias() will also do the right thing (equivalent of
d_add(dentry, NULL); return NULL;), so that kind of special cases
also doesn't need a separate treatment.
--
[strongly recommended]
take the RCU-delayed parts of ->destroy_inode() into a new method -
->free_inode(). If ->destroy_inode() becomes empty - all the better,
just get rid of it. Synchronous work (e.g. the stuff that can't
be done from an RCU callback, or any WARN_ON() where we want the
stack trace) *might* be movable to ->evict_inode(); however,
that goes only for the things that are not needed to balance something
done by ->alloc_inode(). IOW, if it's cleaning up the stuff that
might have accumulated over the life of in-core inode, ->evict_inode()
might be a fit.

Rules for inode destruction:
* if ->destroy_inode() is non-NULL, it gets called
* if ->free_inode() is non-NULL, it gets scheduled by call_rcu()
* combination of NULL ->destroy_inode and NULL ->free_inode is
treated as NULL/free_inode_nonrcu, to preserve the compatibility.

Note that the callback (be it via ->free_inode() or explicit call_rcu()
in ->destroy_inode()) is *NOT* ordered wrt superblock destruction;
as the matter of fact, the superblock and all associated structures
might be already gone. The filesystem driver is guaranteed to be still
there, but that's it. Freeing memory in the callback is fine; doing
more than that is possible, but requires a lot of care and is best
avoided.
10 changes: 2 additions & 8 deletions arch/powerpc/platforms/cell/spufs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,11 @@ spufs_alloc_inode(struct super_block *sb)
return &ei->vfs_inode;
}

static void spufs_i_callback(struct rcu_head *head)
static void spufs_free_inode(struct inode *inode)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
kmem_cache_free(spufs_inode_cache, SPUFS_I(inode));
}

static void spufs_destroy_inode(struct inode *inode)
{
call_rcu(&inode->i_rcu, spufs_i_callback);
}

static void
spufs_init_once(void *p)
{
Expand Down Expand Up @@ -739,7 +733,7 @@ spufs_fill_super(struct super_block *sb, void *data, int silent)
struct spufs_sb_info *info;
static const struct super_operations s_ops = {
.alloc_inode = spufs_alloc_inode,
.destroy_inode = spufs_destroy_inode,
.free_inode = spufs_free_inode,
.statfs = simple_statfs,
.evict_inode = spufs_evict_inode,
.show_options = spufs_show_options,
Expand Down
7 changes: 2 additions & 5 deletions drivers/dax/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,11 +412,9 @@ static struct dax_device *to_dax_dev(struct inode *inode)
return container_of(inode, struct dax_device, inode);
}

static void dax_i_callback(struct rcu_head *head)
static void dax_free_inode(struct inode *inode)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
struct dax_device *dax_dev = to_dax_dev(inode);

kfree(dax_dev->host);
dax_dev->host = NULL;
if (inode->i_rdev)
Expand All @@ -427,16 +425,15 @@ static void dax_i_callback(struct rcu_head *head)
static void dax_destroy_inode(struct inode *inode)
{
struct dax_device *dax_dev = to_dax_dev(inode);

WARN_ONCE(test_bit(DAXDEV_ALIVE, &dax_dev->flags),
"kill_dax() must be called before final iput()\n");
call_rcu(&inode->i_rcu, dax_i_callback);
}

static const struct super_operations dax_sops = {
.statfs = simple_statfs,
.alloc_inode = dax_alloc_inode,
.destroy_inode = dax_destroy_inode,
.free_inode = dax_free_inode,
.drop_inode = generic_delete_inode,
};

Expand Down
10 changes: 2 additions & 8 deletions drivers/staging/erofs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,8 @@ static struct inode *alloc_inode(struct super_block *sb)
return &vi->vfs_inode;
}

static void i_callback(struct rcu_head *head)
static void free_inode(struct inode *inode)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
struct erofs_vnode *vi = EROFS_V(inode);

/* be careful RCU symlink path (see ext4_inode_info->i_data)! */
Expand All @@ -71,11 +70,6 @@ static void i_callback(struct rcu_head *head)
kmem_cache_free(erofs_inode_cachep, vi);
}

static void destroy_inode(struct inode *inode)
{
call_rcu(&inode->i_rcu, i_callback);
}

static int superblock_read(struct super_block *sb)
{
struct erofs_sb_info *sbi;
Expand Down Expand Up @@ -668,7 +662,7 @@ static int erofs_remount(struct super_block *sb, int *flags, char *data)
const struct super_operations erofs_sops = {
.put_super = erofs_put_super,
.alloc_inode = alloc_inode,
.destroy_inode = destroy_inode,
.free_inode = free_inode,
.statfs = erofs_statfs,
.show_options = erofs_show_options,
.remount_fs = erofs_remount,
Expand Down
2 changes: 1 addition & 1 deletion fs/9p/v9fs_vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ extern const struct file_operations v9fs_mmap_file_operations_dotl;
extern struct kmem_cache *v9fs_inode_cache;

struct inode *v9fs_alloc_inode(struct super_block *sb);
void v9fs_destroy_inode(struct inode *inode);
void v9fs_free_inode(struct inode *inode);
struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t);
int v9fs_init_inode(struct v9fs_session_info *v9ses,
struct inode *inode, umode_t mode, dev_t);
Expand Down
10 changes: 2 additions & 8 deletions fs/9p/vfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,21 +253,15 @@ struct inode *v9fs_alloc_inode(struct super_block *sb)
}

/**
* v9fs_destroy_inode - destroy an inode
* v9fs_free_inode - destroy an inode
*
*/

static void v9fs_i_callback(struct rcu_head *head)
void v9fs_free_inode(struct inode *inode)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
kmem_cache_free(v9fs_inode_cache, V9FS_I(inode));
}

void v9fs_destroy_inode(struct inode *inode)
{
call_rcu(&inode->i_rcu, v9fs_i_callback);
}

int v9fs_init_inode(struct v9fs_session_info *v9ses,
struct inode *inode, umode_t mode, dev_t rdev)
{
Expand Down
4 changes: 2 additions & 2 deletions fs/9p/vfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ static int v9fs_write_inode_dotl(struct inode *inode,

static const struct super_operations v9fs_super_ops = {
.alloc_inode = v9fs_alloc_inode,
.destroy_inode = v9fs_destroy_inode,
.free_inode = v9fs_free_inode,
.statfs = simple_statfs,
.evict_inode = v9fs_evict_inode,
.show_options = v9fs_show_options,
Expand All @@ -354,7 +354,7 @@ static const struct super_operations v9fs_super_ops = {

static const struct super_operations v9fs_super_ops_dotl = {
.alloc_inode = v9fs_alloc_inode,
.destroy_inode = v9fs_destroy_inode,
.free_inode = v9fs_free_inode,
.statfs = v9fs_statfs,
.drop_inode = v9fs_drop_inode,
.evict_inode = v9fs_evict_inode,
Expand Down
10 changes: 2 additions & 8 deletions fs/adfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,17 +248,11 @@ static struct inode *adfs_alloc_inode(struct super_block *sb)
return &ei->vfs_inode;
}

static void adfs_i_callback(struct rcu_head *head)
static void adfs_free_inode(struct inode *inode)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
kmem_cache_free(adfs_inode_cachep, ADFS_I(inode));
}

static void adfs_destroy_inode(struct inode *inode)
{
call_rcu(&inode->i_rcu, adfs_i_callback);
}

static void init_once(void *foo)
{
struct adfs_inode_info *ei = (struct adfs_inode_info *) foo;
Expand Down Expand Up @@ -290,7 +284,7 @@ static void destroy_inodecache(void)

static const struct super_operations adfs_sops = {
.alloc_inode = adfs_alloc_inode,
.destroy_inode = adfs_destroy_inode,
.free_inode = adfs_free_inode,
.drop_inode = generic_delete_inode,
.write_inode = adfs_write_inode,
.put_super = adfs_put_super,
Expand Down
10 changes: 2 additions & 8 deletions fs/affs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,11 @@ static struct inode *affs_alloc_inode(struct super_block *sb)
return &i->vfs_inode;
}

static void affs_i_callback(struct rcu_head *head)
static void affs_free_inode(struct inode *inode)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
kmem_cache_free(affs_inode_cachep, AFFS_I(inode));
}

static void affs_destroy_inode(struct inode *inode)
{
call_rcu(&inode->i_rcu, affs_i_callback);
}

static void init_once(void *foo)
{
struct affs_inode_info *ei = (struct affs_inode_info *) foo;
Expand Down Expand Up @@ -155,7 +149,7 @@ static void destroy_inodecache(void)

static const struct super_operations affs_sops = {
.alloc_inode = affs_alloc_inode,
.destroy_inode = affs_destroy_inode,
.free_inode = affs_free_inode,
.write_inode = affs_write_inode,
.evict_inode = affs_evict_inode,
.put_super = affs_put_super,
Expand Down
9 changes: 4 additions & 5 deletions fs/afs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ static void afs_i_init_once(void *foo);
static void afs_kill_super(struct super_block *sb);
static struct inode *afs_alloc_inode(struct super_block *sb);
static void afs_destroy_inode(struct inode *inode);
static void afs_free_inode(struct inode *inode);
static int afs_statfs(struct dentry *dentry, struct kstatfs *buf);
static int afs_show_devname(struct seq_file *m, struct dentry *root);
static int afs_show_options(struct seq_file *m, struct dentry *root);
Expand All @@ -56,6 +57,7 @@ static const struct super_operations afs_super_ops = {
.alloc_inode = afs_alloc_inode,
.drop_inode = afs_drop_inode,
.destroy_inode = afs_destroy_inode,
.free_inode = afs_free_inode,
.evict_inode = afs_evict_inode,
.show_devname = afs_show_devname,
.show_options = afs_show_options,
Expand Down Expand Up @@ -660,11 +662,9 @@ static struct inode *afs_alloc_inode(struct super_block *sb)
return &vnode->vfs_inode;
}

static void afs_i_callback(struct rcu_head *head)
static void afs_free_inode(struct inode *inode)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
struct afs_vnode *vnode = AFS_FS_I(inode);
kmem_cache_free(afs_inode_cachep, vnode);
kmem_cache_free(afs_inode_cachep, AFS_FS_I(inode));
}

/*
Expand All @@ -680,7 +680,6 @@ static void afs_destroy_inode(struct inode *inode)

ASSERTCMP(vnode->cb_interest, ==, NULL);

call_rcu(&inode->i_rcu, afs_i_callback);
atomic_dec(&afs_count_active_inodes);
}

Expand Down
12 changes: 3 additions & 9 deletions fs/befs/linuxvfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ static struct dentry *befs_lookup(struct inode *, struct dentry *,
unsigned int);
static struct inode *befs_iget(struct super_block *, unsigned long);
static struct inode *befs_alloc_inode(struct super_block *sb);
static void befs_destroy_inode(struct inode *inode);
static void befs_free_inode(struct inode *inode);
static void befs_destroy_inodecache(void);
static int befs_symlink_readpage(struct file *, struct page *);
static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
Expand All @@ -64,7 +64,7 @@ static struct dentry *befs_get_parent(struct dentry *child);

static const struct super_operations befs_sops = {
.alloc_inode = befs_alloc_inode, /* allocate a new inode */
.destroy_inode = befs_destroy_inode, /* deallocate an inode */
.free_inode = befs_free_inode, /* deallocate an inode */
.put_super = befs_put_super, /* uninit super */
.statfs = befs_statfs, /* statfs */
.remount_fs = befs_remount,
Expand Down Expand Up @@ -281,17 +281,11 @@ befs_alloc_inode(struct super_block *sb)
return &bi->vfs_inode;
}

static void befs_i_callback(struct rcu_head *head)
static void befs_free_inode(struct inode *inode)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
kmem_cache_free(befs_inode_cachep, BEFS_I(inode));
}

static void befs_destroy_inode(struct inode *inode)
{
call_rcu(&inode->i_rcu, befs_i_callback);
}

static void init_once(void *foo)
{
struct befs_inode_info *bi = (struct befs_inode_info *) foo;
Expand Down
10 changes: 2 additions & 8 deletions fs/bfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,17 +245,11 @@ static struct inode *bfs_alloc_inode(struct super_block *sb)
return &bi->vfs_inode;
}

static void bfs_i_callback(struct rcu_head *head)
static void bfs_free_inode(struct inode *inode)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
kmem_cache_free(bfs_inode_cachep, BFS_I(inode));
}

static void bfs_destroy_inode(struct inode *inode)
{
call_rcu(&inode->i_rcu, bfs_i_callback);
}

static void init_once(void *foo)
{
struct bfs_inode_info *bi = foo;
Expand Down Expand Up @@ -287,7 +281,7 @@ static void destroy_inodecache(void)

static const struct super_operations bfs_sops = {
.alloc_inode = bfs_alloc_inode,
.destroy_inode = bfs_destroy_inode,
.free_inode = bfs_free_inode,
.write_inode = bfs_write_inode,
.evict_inode = bfs_evict_inode,
.put_super = bfs_put_super,
Expand Down
14 changes: 3 additions & 11 deletions fs/block_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -790,17 +790,9 @@ static struct inode *bdev_alloc_inode(struct super_block *sb)
return &ei->vfs_inode;
}

static void bdev_i_callback(struct rcu_head *head)
static void bdev_free_inode(struct inode *inode)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
struct bdev_inode *bdi = BDEV_I(inode);

kmem_cache_free(bdev_cachep, bdi);
}

static void bdev_destroy_inode(struct inode *inode)
{
call_rcu(&inode->i_rcu, bdev_i_callback);
kmem_cache_free(bdev_cachep, BDEV_I(inode));
}

static void init_once(void *foo)
Expand Down Expand Up @@ -840,7 +832,7 @@ static void bdev_evict_inode(struct inode *inode)
static const struct super_operations bdev_sops = {
.statfs = simple_statfs,
.alloc_inode = bdev_alloc_inode,
.destroy_inode = bdev_destroy_inode,
.free_inode = bdev_free_inode,
.drop_inode = generic_delete_inode,
.evict_inode = bdev_evict_inode,
};
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3267,6 +3267,7 @@ void btrfs_evict_inode(struct inode *inode);
int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc);
struct inode *btrfs_alloc_inode(struct super_block *sb);
void btrfs_destroy_inode(struct inode *inode);
void btrfs_free_inode(struct inode *inode);
int btrfs_drop_inode(struct inode *inode);
int __init btrfs_init_cachep(void);
void __cold btrfs_destroy_cachep(void);
Expand Down
Loading

0 comments on commit 168e153

Please sign in to comment.