fs: improve scalability of pseudo filesystems
authorNick Piggin <npiggin@kernel.dk>
Fri, 7 Jan 2011 06:50:07 +0000 (17:50 +1100)
committerNick Piggin <npiggin@kernel.dk>
Fri, 7 Jan 2011 06:50:32 +0000 (17:50 +1100)
Regardless of how much we possibly try to scale dcache, there is likely
always going to be some fundamental contention when adding or removing children
under the same parent. Pseudo filesystems do not seem need to have connected
dentries because by definition they are disconnected.

Signed-off-by: Nick Piggin <npiggin@kernel.dk>
fs/anon_inodes.c
fs/dcache.c
fs/pipe.c
include/linux/dcache.h
net/socket.c

index aca8806fa20697551b89d11bc00d7220338ce085..9d92b33da8a0c1286bb9144a9f86c68c0d36a750 100644 (file)
@@ -102,7 +102,7 @@ struct file *anon_inode_getfile(const char *name,
        this.name = name;
        this.len = strlen(name);
        this.hash = 0;
-       path.dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
+       path.dentry = d_alloc_pseudo(anon_inode_mnt->mnt_sb, &this);
        if (!path.dentry)
                goto err_module;
 
index 09ec945f3c98f68b601af8e39c6ada900d79903f..9e6e6db76869b7770a8c8110698b40eae27a2d0d 100644 (file)
@@ -1330,6 +1330,18 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
 }
 EXPORT_SYMBOL(d_alloc);
 
+struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name)
+{
+       struct dentry *dentry = d_alloc(NULL, name);
+       if (dentry) {
+               dentry->d_sb = sb;
+               dentry->d_parent = dentry;
+               dentry->d_flags |= DCACHE_DISCONNECTED;
+       }
+       return dentry;
+}
+EXPORT_SYMBOL(d_alloc_pseudo);
+
 struct dentry *d_alloc_name(struct dentry *parent, const char *name)
 {
        struct qstr q;
index 01a786567810cb0ffa38b3dd1a1a0ee23d1870b4..cfe3a7f2ee21079ee0fd154837d2f58061a30e15 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -999,7 +999,7 @@ struct file *create_write_pipe(int flags)
                goto err;
 
        err = -ENOMEM;
-       path.dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name);
+       path.dentry = d_alloc_pseudo(pipe_mnt->mnt_sb, &name);
        if (!path.dentry)
                goto err_inode;
        path.mnt = mntget(pipe_mnt);
index d719e4de8046eb46d550e19770129265d8196f59..c0a2ca97c72fcd21a9466185f44337909d4b816c 100644 (file)
@@ -211,6 +211,7 @@ extern void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op
 
 /* allocate/de-allocate */
 extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
+extern struct dentry * d_alloc_pseudo(struct super_block *, const struct qstr *);
 extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
 extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
 extern struct dentry * d_obtain_alias(struct inode *);
index 991e266bc7aeb3ecba72edc69ec539e0640b6629..0ee74c325320700f5b2bde733c6869804d486fd5 100644 (file)
@@ -361,7 +361,7 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
        if (unlikely(fd < 0))
                return fd;
 
-       path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
+       path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
        if (unlikely(!path.dentry)) {
                put_unused_fd(fd);
                return -ENOMEM;