Omar Sandoval <osandov@xxxxxxxxxxx> writes: > On Fri, May 15, 2015 at 08:58:20PM +0200, Ivan Delalande wrote: >> Hi, >> >> I’m still struggling to understand all the relations between the VFS >> structures and at which point they get initialized precisely. Do you >> have any idea how to fix this problem? The relationships in this case are quite odd and can be simplified. > I'm attaching a minimal script that reproduces this on 4.1-rc4. I'm > taking a look, but Eric or Al will probably figure this out before I get > the chance :) This works for me, can you confirm it works for you folks as well? Thank you, Eric From: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> Date: Wed, 20 May 2015 16:39:00 -0500 Subject: [PATCH] vfs: Fix, simpliy and stop using d_dname for the /proc/*/ns/* files. Now that these files are no longer in proc we can stop playing games with d_alloc_pseudo and d_dname. This change causes a couple of user visible changes: - Opening /proc/*/ns/* and then readlink on /proc/self/fd/N now sees a prepended / in the filename. - /proc/mountinfo now gives useful information on what is mounted. - Bind mounting /proc/*/ns/*, opening the mounted file, removing the bind mount, and readlink on /proc/self/fd/N now sees / (as it should) instead of triggering a warning and a kernel stack backtrace from prepend_path. Cc: stable@xxxxxxxxxxxxxxx Reported-by: Ivan Delalande <colona@xxxxxxxxxx> Reported-by: Omar Sandoval <osandov@xxxxxxxxxxx> Signed-off-by: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> --- fs/dcache.c | 7 +------ fs/nsfs.c | 19 +++++-------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 656ce522a218..e0f0967ef24c 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -3087,13 +3087,8 @@ char *d_path(const struct path *path, char *buf, int buflen) * thus don't need to be hashed. They also don't need a name until a * user wants to identify the object in /proc/pid/fd/. The little hack * below allows us to generate a name for these objects on demand: - * - * Some pseudo inodes are mountable. When they are mounted - * path->dentry == path->mnt->mnt_root. In that case don't call d_dname - * and instead have d_path return the mounted path. */ - if (path->dentry->d_op && path->dentry->d_op->d_dname && - (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root)) + if (path->dentry->d_op && path->dentry->d_op->d_dname) return path->dentry->d_op->d_dname(path->dentry, buf, buflen); rcu_read_lock(); diff --git a/fs/nsfs.c b/fs/nsfs.c index 99521e7c492b..b9ecfa6cb46d 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -11,15 +11,6 @@ static const struct file_operations ns_file_operations = { .llseek = no_llseek, }; -static char *ns_dname(struct dentry *dentry, char *buffer, int buflen) -{ - struct inode *inode = d_inode(dentry); - const struct proc_ns_operations *ns_ops = dentry->d_fsdata; - - return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]", - ns_ops->name, inode->i_ino); -} - static void ns_prune_dentry(struct dentry *dentry) { struct inode *inode = d_inode(dentry); @@ -33,7 +24,6 @@ const struct dentry_operations ns_dentry_operations = { .d_prune = ns_prune_dentry, .d_delete = always_delete_dentry, - .d_dname = ns_dname, }; static void nsfs_evict(struct inode *inode) @@ -47,7 +37,7 @@ void *ns_get_path(struct path *path, struct task_struct *task, const struct proc_ns_operations *ns_ops) { struct vfsmount *mnt = mntget(nsfs_mnt); - struct qstr qname = { .name = "", }; + char name[DNAME_INLINE_LEN]; struct dentry *dentry; struct inode *inode; struct ns_common *ns; @@ -80,6 +70,7 @@ slow: mntput(mnt); return ERR_PTR(-ENOMEM); } + snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns->inum); inode->i_ino = ns->inum; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_flags |= S_IMMUTABLE; @@ -87,13 +78,13 @@ slow: inode->i_fop = &ns_file_operations; inode->i_private = ns; - dentry = d_alloc_pseudo(mnt->mnt_sb, &qname); + dentry = d_alloc_name(mnt->mnt_root, name); if (!dentry) { iput(inode); mntput(mnt); return ERR_PTR(-ENOMEM); } - d_instantiate(dentry, inode); + d_add(dentry, inode); dentry->d_fsdata = (void *)ns_ops; d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry); if (d) { @@ -143,7 +134,7 @@ static const struct super_operations nsfs_ops = { static struct dentry *nsfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_pseudo(fs_type, "nsfs:", &nsfs_ops, + return mount_pseudo(fs_type, "/", &nsfs_ops, &ns_dentry_operations, NSFS_MAGIC); } static struct file_system_type nsfs = { -- 2.2.1 -- 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