lkml.org 
[lkml]   [2011]   [Jul]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH] vfs: dont chain pipe/anon/socket on superblock s_inodes list
    From
    Date
    Le mardi 26 juillet 2011 à 08:00 +0200, Eric Dumazet a écrit :

    > Next step is to not chain pipes/sockets into superblock s_inodes list
    >
    > inode_sb_list_add()/inode_sb_list_del() is the very last contention
    > point because of spin_lock(&inode_sb_list_lock);

    Well, not 'last' contention point, as we still hit remove_inode_hash(),
    inode_wb_list_del(), inode_lru_list_del(), but thats a clear win on my
    2x4x2 machine : 9 seconds instead of 22 on a close(socket()) benchmark.


    [PATCH] 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: Eric Dumazet <eric.dumazet@gmail.com>
    ---
    fs/anon_inodes.c | 2 +-
    fs/inode.c | 31 +++++++++++++++++++++----------
    fs/pipe.c | 2 +-
    include/linux/fs.h | 3 ++-
    net/socket.c | 2 +-
    5 files changed, 26 insertions(+), 14 deletions(-)

    diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
    index 4d433d3..269499e 100644
    --- a/fs/anon_inodes.c
    +++ b/fs/anon_inodes.c
    @@ -187,7 +187,7 @@ EXPORT_SYMBOL_GPL(anon_inode_getfd);
    */
    static struct inode *anon_inode_mkinode(void)
    {
    - struct inode *inode = new_inode(anon_inode_mnt->mnt_sb);
    + struct inode *inode = __new_inode(anon_inode_mnt->mnt_sb);

    if (!inode)
    return ERR_PTR(-ENOMEM);
    diff --git a/fs/inode.c b/fs/inode.c
    index 96c77b8..8a6d62b 100644
    --- a/fs/inode.c
    +++ b/fs/inode.c
    @@ -362,9 +362,11 @@ EXPORT_SYMBOL_GPL(inode_sb_list_add);

    static inline void inode_sb_list_del(struct inode *inode)
    {
    - spin_lock(&inode_sb_list_lock);
    - list_del_init(&inode->i_sb_list);
    - spin_unlock(&inode_sb_list_lock);
    + if (!list_empty(&inode->i_sb_list)) {
    + spin_lock(&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)
    @@ -796,6 +798,19 @@ unsigned int get_next_ino(void)
    }
    EXPORT_SYMBOL(get_next_ino);

    +struct inode *__new_inode(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
    * @sb: superblock
    @@ -814,13 +829,9 @@ struct inode *new_inode(struct super_block *sb)

    spin_lock_prefetch(&inode_sb_list_lock);

    - inode = alloc_inode(sb);
    - if (inode) {
    - spin_lock(&inode->i_lock);
    - inode->i_state = 0;
    - spin_unlock(&inode->i_lock);
    - inode_sb_list_add(inode);
    - }
    + inode = __new_inode(sb);
    + if (inode)
    + inode_sb_list_add(inode);
    return inode;
    }
    EXPORT_SYMBOL(new_inode);
    diff --git a/fs/pipe.c b/fs/pipe.c
    index 1b7f9af..937b962 100644
    --- a/fs/pipe.c
    +++ b/fs/pipe.c
    @@ -948,7 +948,7 @@ static const struct dentry_operations pipefs_dentry_operations = {

    static struct inode * get_pipe_inode(void)
    {
    - struct inode *inode = new_inode(pipe_mnt->mnt_sb);
    + struct inode *inode = __new_inode(pipe_mnt->mnt_sb);
    struct pipe_inode_info *pipe;

    if (!inode)
    diff --git a/include/linux/fs.h b/include/linux/fs.h
    index a665804..60be54f 100644
    --- a/include/linux/fs.h
    +++ b/include/linux/fs.h
    @@ -2310,7 +2310,8 @@ extern void __iget(struct inode * inode);
    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 struct inode *__new_inode(struct super_block *sb);
    +extern struct inode *new_inode(struct super_block *sb);
    extern void free_inode_nonrcu(struct inode *inode);
    extern int should_remove_suid(struct dentry *);
    extern int file_remove_suid(struct file *);
    diff --git a/net/socket.c b/net/socket.c
    index 02dc82d..b4b8a08 100644
    --- a/net/socket.c
    +++ b/net/socket.c
    @@ -467,7 +467,7 @@ static struct socket *sock_alloc(void)
    struct inode *inode;
    struct socket *sock;

    - inode = new_inode(sock_mnt->mnt_sb);
    + inode = __new_inode(sock_mnt->mnt_sb);
    if (!inode)
    return NULL;


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2011-07-26 10:23    [W:0.026 / U:31.980 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site