From: Miklos Szeredi <mszeredi@xxxxxxx> "vfs: fix d_path() for unreachable paths" prefixes unreachable paths with "(unreachable)" in the result of getcwd(2), /proc/*/mounts, /proc/*/cwd, /proc/*/fd/*, etc... Hugh Dickins reported that an old version of gnome-vfs-daemon crashes because it finds an entry in /proc/mounts where the mountpoint is unreachable. This patch reverts /proc/mounts to the old behavior (or rather a less crazy version of the old behavior). Reported-by: Hugh Dickins <hugh.dickins@xxxxxxxxxxxxx> Acked-by: Hugh Dickins <hugh.dickins@xxxxxxxxxxxxx> Reported-by: Valdis Kletnieks <Valdis.Kletnieks@xxxxxx> Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxx> Cc: Matthew Wilcox <matthew@xxxxxx> Cc: Andreas Gruenbacher <agruen@xxxxxxx> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- fs/namespace.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff -puN fs/namespace.c~vfs-revert-proc-mounts-to-old-behavior-for-unreachable-mountpoints fs/namespace.c --- a/fs/namespace.c~vfs-revert-proc-mounts-to-old-behavior-for-unreachable-mountpoints +++ a/fs/namespace.c @@ -789,6 +789,61 @@ static void show_type(struct seq_file *m } } +/* + * Same as d_path() except it doesn't stick "(unreachable)" in front + * of unreachable paths. + */ +static char *d_path_compat(struct path *path, char *buf, int buflen) +{ + char *res; + struct path root; + struct path tmp; + + read_lock(¤t->fs->lock); + root = current->fs->root; + path_get(&root); + read_unlock(¤t->fs->lock); + spin_lock(&dcache_lock); + tmp = root; + res = __d_path(path, &tmp, buf, buflen); + if (!IS_ERR(res) && + (tmp.mnt != root.mnt || tmp.dentry != root.dentry)) { + /* + * Unreachable path found, redo with the global root + * so we get a normal looking path. + */ + res = __d_path(path, &tmp, buf, buflen); + } + spin_unlock(&dcache_lock); + path_put(&root); + + return res; +} + +/* + * Some old programs break if /proc/mounts contains a mountpoint + * beginning with "(unreachable)". Revert this back to the old way of + * displaying the path from the global root instead. + */ +static int show_path_old(struct seq_file *m, struct path *path, char *esc) +{ + char *buf; + size_t size = seq_get_buf(m, &buf); + int res = -1; + + if (size) { + char *p = d_path_compat(path, buf, size); + if (!IS_ERR(p)) { + char *end = mangle_path(buf, p, esc); + if (end) + res = end - buf; + } + } + seq_commit(m, res); + + return res; +} + static int show_vfsmnt(struct seq_file *m, void *v) { struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); @@ -797,7 +852,7 @@ static int show_vfsmnt(struct seq_file * mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); seq_putc(m, ' '); - seq_path(m, &mnt_path, " \t\n\\"); + show_path_old(m, &mnt_path, " \t\n\\"); seq_putc(m, ' '); show_type(m, mnt->mnt_sb); seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw"); _ -- 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