Skip to content

Commit

Permalink
[PATCH] net: don't insert socket dentries into dentry_hashtable
Browse files Browse the repository at this point in the history
We currently insert socket dentries into the global dentry hashtable.  This
is suboptimal because there is currently no way these entries can be used
for a lookup().  (/proc/xxx/fd/xxx uses a different mechanism).  Inserting
them in dentry hashtable slows dcache lookups.

To let __dpath() still work correctly (ie not adding a " (deleted)") after
dentry name, we do :

- Right after d_alloc(), pretend they are hashed by clearing the
  DCACHE_UNHASHED bit.

- Call d_instantiate() instead of d_add() : dentry is not inserted in
  hash table.

  __dpath() & friends work as intended during dentry lifetime.

- At dismantle time, once dput() must clear the dentry, setting again
  DCACHE_UNHASHED bit inside the custom d_delete() function provided by
  socket code, so that dput() can just kill_it.

Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Eric Dumazet authored and Linus Torvalds committed Dec 7, 2006
1 parent b342341 commit 304e61e
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions net/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,14 @@ static struct file_system_type sock_fs_type = {

static int sockfs_delete_dentry(struct dentry *dentry)
{
return 1;
/*
* At creation time, we pretended this dentry was hashed
* (by clearing DCACHE_UNHASHED bit in d_flags)
* At delete time, we restore the truth : not hashed.
* (so that dput() can proceed correctly)
*/
dentry->d_flags |= DCACHE_UNHASHED;
return 0;
}
static struct dentry_operations sockfs_dentry_operations = {
.d_delete = sockfs_delete_dentry,
Expand Down Expand Up @@ -353,14 +360,20 @@ static int sock_attach_fd(struct socket *sock, struct file *file)

this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
this.name = name;
this.hash = SOCK_INODE(sock)->i_ino;
this.hash = 0;

file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
if (unlikely(!file->f_dentry))
return -ENOMEM;

file->f_dentry->d_op = &sockfs_dentry_operations;
d_add(file->f_dentry, SOCK_INODE(sock));
/*
* We dont want to push this dentry into global dentry hash table.
* We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
* This permits a working /proc/$pid/fd/XXX on sockets
*/
file->f_dentry->d_flags &= ~DCACHE_UNHASHED;
d_instantiate(file->f_dentry, SOCK_INODE(sock));
file->f_vfsmnt = mntget(sock_mnt);
file->f_mapping = file->f_dentry->d_inode->i_mapping;

Expand Down

0 comments on commit 304e61e

Please sign in to comment.