From: Al Viro <viro@xxxxxxxxxxxxxxxxxx> we can do fdput() under rcu_read_lock() just fine; all we need to take care of is fetching nd->inode value first. Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx> --- fs/namei.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 6f95bc9..497d5f4 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -503,7 +503,6 @@ struct nameidata { int last_type; unsigned depth; int total_link_count; - struct file *base; struct saved { struct path link; void *cookie; @@ -1872,7 +1871,6 @@ static int path_init(int dfd, const struct filename *name, unsigned int flags, nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT; nd->depth = 0; - nd->base = NULL; if (flags & LOOKUP_ROOT) { struct dentry *root = nd->root.dentry; struct inode *inode = root->d_inode; @@ -1941,14 +1939,15 @@ static int path_init(int dfd, const struct filename *name, unsigned int flags, nd->path = f.file->f_path; if (flags & LOOKUP_RCU) { - if (f.flags & FDPUT_FPUT) - nd->base = f.file; - nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); rcu_read_lock(); + nd->inode = nd->path.dentry->d_inode; + nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); } else { path_get(&nd->path); - fdput(f); + nd->inode = nd->path.dentry->d_inode; } + fdput(f); + goto done; } nd->inode = nd->path.dentry->d_inode; @@ -1971,8 +1970,6 @@ static void path_cleanup(struct nameidata *nd) path_put(&nd->root); nd->root.mnt = NULL; } - if (unlikely(nd->base)) - fput(nd->base); } static int trailing_symlink(struct nameidata *nd) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html