Here's a patch for reference (untested): diff --git a/fs/namei.c b/fs/namei.c index a7b05bf..84704e4 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -649,17 +649,15 @@ static __always_inline void set_root(struct nameidata *nd) static int link_path_walk(const char *, struct nameidata *); -static __always_inline unsigned set_root_rcu(struct nameidata *nd) +static __always_inline void set_root_rcu(struct nameidata *nd) { struct fs_struct *fs = current->fs; - unsigned seq, res; + unsigned seq; do { seq = read_seqcount_begin(&fs->seq); nd->root = fs->root; - res = __read_seqcount_begin(&nd->root.dentry->d_seq); } while (read_seqcount_retry(&fs->seq, seq)); - return res; } static void path_put_conditional(struct path *path, struct nameidata *nd) @@ -1854,11 +1852,21 @@ static int path_init(int dfd, const char *name, unsigned int flags, nd->m_seq = read_seqbegin(&mount_lock); if (*name=='/') { if (flags & LOOKUP_RCU) { + struct fs_struct *fs = current->fs; + unsigned seq; + rcu_read_lock(); - nd->seq = set_root_rcu(nd); + + do { + seq = read_seqcount_begin(&fs->seq); + nd->root = fs->root; + nd->inode = nd->root.dentry->d_inode; + nd->seq = __read_seqcount_begin(&nd->root.dentry->d_seq); + } while (read_seqcount_retry(&fs->seq, seq)); } else { set_root(nd); path_get(&nd->root); + nd->inode = nd->root.dentry->d_inode; } nd->path = nd->root; } else if (dfd == AT_FDCWD) { @@ -1871,10 +1879,12 @@ static int path_init(int dfd, const char *name, unsigned int flags, do { seq = read_seqcount_begin(&fs->seq); nd->path = fs->pwd; + nd->inode = nd->path.dentry->d_inode; nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); } while (read_seqcount_retry(&fs->seq, seq)); } else { get_fs_pwd(current->fs, &nd->path); + nd->inode = nd->path.dentry->d_inode; } } else { /* Caller must check execute permissions on the starting path component */ @@ -1894,6 +1904,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, } nd->path = f.file->f_path; + nd->inode = file_inode(f.file); if (flags & LOOKUP_RCU) { if (f.flags & FDPUT_FPUT) *fp = f.file; @@ -1904,16 +1915,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, fdput(f); } } - - nd->inode = nd->path.dentry->d_inode; - if (!(flags & LOOKUP_RCU)) - return 0; - if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq))) - return 0; - if (!(nd->flags & LOOKUP_ROOT)) - nd->root.mnt = NULL; - rcu_read_unlock(); - return -ECHILD; + return 0; } static inline int lookup_last(struct nameidata *nd, struct path *path) -- 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