|
@@ -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;
|