[PATCH] don't insert pipe dentries into dentry_hashtable.
We currently insert pipe 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 pipe code, so that dput() can just kill_it. This patch, combined with (avoid RCU for never hashed dentries) reduced time of { pipe(p); close(p[0]); close(p[1]);} on my UP machine (1.6GHz Pentium-M) from 3.23 us to 2.86 us (But this patch does not depend on other patches, only bench results) Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> Acked-by: David Miller <davem@davemloft.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
1c69d921ed
Коммит
d18de5a272
22
fs/pipe.c
22
fs/pipe.c
|
@ -830,7 +830,14 @@ void free_pipe_info(struct inode *inode)
|
|||
static struct vfsmount *pipe_mnt __read_mostly;
|
||||
static int pipefs_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 pipefs_dentry_operations = {
|
||||
|
@ -891,17 +898,22 @@ struct file *create_write_pipe(void)
|
|||
if (!inode)
|
||||
goto err_file;
|
||||
|
||||
sprintf(name, "[%lu]", inode->i_ino);
|
||||
this.len = sprintf(name, "[%lu]", inode->i_ino);
|
||||
this.name = name;
|
||||
this.len = strlen(name);
|
||||
this.hash = inode->i_ino; /* will go */
|
||||
this.hash = 0;
|
||||
err = -ENOMEM;
|
||||
dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this);
|
||||
if (!dentry)
|
||||
goto err_inode;
|
||||
|
||||
dentry->d_op = &pipefs_dentry_operations;
|
||||
d_add(dentry, inode);
|
||||
/*
|
||||
* We dont want to publish 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 pipes
|
||||
*/
|
||||
dentry->d_flags &= ~DCACHE_UNHASHED;
|
||||
d_instantiate(dentry, inode);
|
||||
f->f_vfsmnt = mntget(pipe_mnt);
|
||||
f->f_dentry = dentry;
|
||||
f->f_mapping = inode->i_mapping;
|
||||
|
|
Загрузка…
Ссылка в новой задаче