Skip to content

Commit

Permalink
fs: avoid inode RCU freeing for pseudo fs
Browse files Browse the repository at this point in the history
Pseudo filesystems that don't put inode on RCU list or reachable by
rcu-walk dentries do not need to RCU free their inodes.

Signed-off-by: Nick Piggin <npiggin@kernel.dk>
  • Loading branch information
Nick Piggin committed Jan 7, 2011
1 parent fa0d7e3 commit ff0c7d1
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 9 deletions.
6 changes: 6 additions & 0 deletions fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,12 @@ static struct inode *alloc_inode(struct super_block *sb)
return inode;
}

void free_inode_nonrcu(struct inode *inode)
{
kmem_cache_free(inode_cachep, inode);
}
EXPORT_SYMBOL(free_inode_nonrcu);

void __destroy_inode(struct inode *inode)
{
BUG_ON(inode_has_buffers(inode));
Expand Down
6 changes: 5 additions & 1 deletion fs/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,10 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
return ret;
}

static const struct super_operations pipefs_ops = {
.destroy_inode = free_inode_nonrcu,
};

/*
* pipefs should _never_ be mounted by userland - too much of security hassle,
* no real gain from having the whole whorehouse mounted. So we don't need
Expand All @@ -1262,7 +1266,7 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
static struct dentry *pipefs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return mount_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC);
return mount_pseudo(fs_type, "pipe:", &pipefs_ops, PIPEFS_MAGIC);
}

static struct file_system_type pipe_fs_type = {
Expand Down
1 change: 1 addition & 0 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2233,6 +2233,7 @@ extern void iget_failed(struct inode *);
extern void end_writeback(struct inode *);
extern void __destroy_inode(struct inode *);
extern struct inode *new_inode(struct super_block *);
extern void free_inode_nonrcu(struct inode *inode);
extern int should_remove_suid(struct dentry *);
extern int file_remove_suid(struct file *);

Expand Down
1 change: 1 addition & 0 deletions include/linux/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ enum sock_shutdown_cmd {
struct socket_wq {
wait_queue_head_t wait;
struct fasync_struct *fasync_list;
struct rcu_head rcu;
} ____cacheline_aligned_in_smp;

/**
Expand Down
17 changes: 9 additions & 8 deletions net/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,20 +262,21 @@ static struct inode *sock_alloc_inode(struct super_block *sb)
}


static void sock_free_rcu(struct rcu_head *head)

static void wq_free_rcu(struct rcu_head *head)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
struct socket_alloc *ei = container_of(inode, struct socket_alloc,
vfs_inode);
struct socket_wq *wq = container_of(head, struct socket_wq, rcu);

kfree(ei->socket.wq);
INIT_LIST_HEAD(&inode->i_dentry);
kmem_cache_free(sock_inode_cachep, ei);
kfree(wq);
}

static void sock_destroy_inode(struct inode *inode)
{
call_rcu(&inode->i_rcu, sock_free_rcu);
struct socket_alloc *ei;

ei = container_of(inode, struct socket_alloc, vfs_inode);
call_rcu(&ei->socket.wq->rcu, wq_free_rcu);
kmem_cache_free(sock_inode_cachep, ei);
}

static void init_once(void *foo)
Expand Down

0 comments on commit ff0c7d1

Please sign in to comment.