提交 a209dfc7 编写于 作者: E Eric Dumazet 提交者: Al Viro

vfs: dont chain pipe/anon/socket on superblock s_inodes list

Workloads using pipes and sockets hit inode_sb_list_lock contention.

superblock s_inodes list is needed for quota, dirty, pagecache and
fsnotify management. pipe/anon/socket fs are clearly not candidates for
these.
Signed-off-by: NEric Dumazet <eric.dumazet@gmail.com>
Reviewed-by: NChristoph Hellwig <hch@lst.de>
Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
上级 5b9f4567
...@@ -187,7 +187,7 @@ EXPORT_SYMBOL_GPL(anon_inode_getfd); ...@@ -187,7 +187,7 @@ EXPORT_SYMBOL_GPL(anon_inode_getfd);
*/ */
static struct inode *anon_inode_mkinode(void) static struct inode *anon_inode_mkinode(void)
{ {
struct inode *inode = new_inode(anon_inode_mnt->mnt_sb); struct inode *inode = new_inode_pseudo(anon_inode_mnt->mnt_sb);
if (!inode) if (!inode)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
......
...@@ -362,9 +362,11 @@ EXPORT_SYMBOL_GPL(inode_sb_list_add); ...@@ -362,9 +362,11 @@ EXPORT_SYMBOL_GPL(inode_sb_list_add);
static inline void inode_sb_list_del(struct inode *inode) static inline void inode_sb_list_del(struct inode *inode)
{ {
spin_lock(&inode_sb_list_lock); if (!list_empty(&inode->i_sb_list)) {
list_del_init(&inode->i_sb_list); spin_lock(&inode_sb_list_lock);
spin_unlock(&inode_sb_list_lock); list_del_init(&inode->i_sb_list);
spin_unlock(&inode_sb_list_lock);
}
} }
static unsigned long hash(struct super_block *sb, unsigned long hashval) static unsigned long hash(struct super_block *sb, unsigned long hashval)
...@@ -796,6 +798,29 @@ unsigned int get_next_ino(void) ...@@ -796,6 +798,29 @@ unsigned int get_next_ino(void)
} }
EXPORT_SYMBOL(get_next_ino); EXPORT_SYMBOL(get_next_ino);
/**
* new_inode_pseudo - obtain an inode
* @sb: superblock
*
* Allocates a new inode for given superblock.
* Inode wont be chained in superblock s_inodes list
* This means :
* - fs can't be unmount
* - quotas, fsnotify, writeback can't work
*/
struct inode *new_inode_pseudo(struct super_block *sb)
{
struct inode *inode = alloc_inode(sb);
if (inode) {
spin_lock(&inode->i_lock);
inode->i_state = 0;
spin_unlock(&inode->i_lock);
INIT_LIST_HEAD(&inode->i_sb_list);
}
return inode;
}
/** /**
* new_inode - obtain an inode * new_inode - obtain an inode
* @sb: superblock * @sb: superblock
...@@ -814,13 +839,9 @@ struct inode *new_inode(struct super_block *sb) ...@@ -814,13 +839,9 @@ struct inode *new_inode(struct super_block *sb)
spin_lock_prefetch(&inode_sb_list_lock); spin_lock_prefetch(&inode_sb_list_lock);
inode = alloc_inode(sb); inode = new_inode_pseudo(sb);
if (inode) { if (inode)
spin_lock(&inode->i_lock);
inode->i_state = 0;
spin_unlock(&inode->i_lock);
inode_sb_list_add(inode); inode_sb_list_add(inode);
}
return inode; return inode;
} }
EXPORT_SYMBOL(new_inode); EXPORT_SYMBOL(new_inode);
......
...@@ -948,7 +948,7 @@ static const struct dentry_operations pipefs_dentry_operations = { ...@@ -948,7 +948,7 @@ static const struct dentry_operations pipefs_dentry_operations = {
static struct inode * get_pipe_inode(void) static struct inode * get_pipe_inode(void)
{ {
struct inode *inode = new_inode(pipe_mnt->mnt_sb); struct inode *inode = new_inode_pseudo(pipe_mnt->mnt_sb);
struct pipe_inode_info *pipe; struct pipe_inode_info *pipe;
if (!inode) if (!inode)
......
...@@ -2310,7 +2310,8 @@ extern void __iget(struct inode * inode); ...@@ -2310,7 +2310,8 @@ extern void __iget(struct inode * inode);
extern void iget_failed(struct inode *); extern void iget_failed(struct inode *);
extern void end_writeback(struct inode *); extern void end_writeback(struct inode *);
extern void __destroy_inode(struct inode *); extern void __destroy_inode(struct inode *);
extern struct inode *new_inode(struct super_block *); extern struct inode *new_inode_pseudo(struct super_block *sb);
extern struct inode *new_inode(struct super_block *sb);
extern void free_inode_nonrcu(struct inode *inode); extern void free_inode_nonrcu(struct inode *inode);
extern int should_remove_suid(struct dentry *); extern int should_remove_suid(struct dentry *);
extern int file_remove_suid(struct file *); extern int file_remove_suid(struct file *);
......
...@@ -467,7 +467,7 @@ static struct socket *sock_alloc(void) ...@@ -467,7 +467,7 @@ static struct socket *sock_alloc(void)
struct inode *inode; struct inode *inode;
struct socket *sock; struct socket *sock;
inode = new_inode(sock_mnt->mnt_sb); inode = new_inode_pseudo(sock_mnt->mnt_sb);
if (!inode) if (!inode)
return NULL; return NULL;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册