diff options
-rw-r--r-- | fs/dcache.c | 24 | ||||
-rw-r--r-- | fs/seq_file.c | 30 | ||||
-rw-r--r-- | include/linux/dcache.h | 1 | ||||
-rw-r--r-- | include/linux/seq_file.h | 2 |
4 files changed, 49 insertions, 8 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 635c2aa427ed..3ee588d5f585 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -1759,10 +1759,8 @@ static int prepend(char **buffer, int *buflen, const char *str, | |||
1759 | 1759 | ||
1760 | /** | 1760 | /** |
1761 | * d_path - return the path of a dentry | 1761 | * d_path - return the path of a dentry |
1762 | * @dentry: dentry to report | 1762 | * @path: the dentry/vfsmount to report |
1763 | * @vfsmnt: vfsmnt to which the dentry belongs | 1763 | * @root: root vfsmnt/dentry (may be modified by this function) |
1764 | * @root: root dentry | ||
1765 | * @rootmnt: vfsmnt to which the root dentry belongs | ||
1766 | * @buffer: buffer to return value in | 1764 | * @buffer: buffer to return value in |
1767 | * @buflen: buffer length | 1765 | * @buflen: buffer length |
1768 | * | 1766 | * |
@@ -1772,10 +1770,15 @@ static int prepend(char **buffer, int *buflen, const char *str, | |||
1772 | * Returns the buffer or an error code if the path was too long. | 1770 | * Returns the buffer or an error code if the path was too long. |
1773 | * | 1771 | * |
1774 | * "buflen" should be positive. Caller holds the dcache_lock. | 1772 | * "buflen" should be positive. Caller holds the dcache_lock. |
1773 | * | ||
1774 | * If path is not reachable from the supplied root, then the value of | ||
1775 | * root is changed (without modifying refcounts). | ||
1775 | */ | 1776 | */ |
1776 | static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt, | 1777 | char *__d_path(const struct path *path, struct path *root, |
1777 | struct path *root, char *buffer, int buflen) | 1778 | char *buffer, int buflen) |
1778 | { | 1779 | { |
1780 | struct dentry *dentry = path->dentry; | ||
1781 | struct vfsmount *vfsmnt = path->mnt; | ||
1779 | char * end = buffer+buflen; | 1782 | char * end = buffer+buflen; |
1780 | char * retval; | 1783 | char * retval; |
1781 | 1784 | ||
@@ -1824,6 +1827,8 @@ global_root: | |||
1824 | if (prepend(&retval, &buflen, dentry->d_name.name, | 1827 | if (prepend(&retval, &buflen, dentry->d_name.name, |
1825 | dentry->d_name.len) != 0) | 1828 | dentry->d_name.len) != 0) |
1826 | goto Elong; | 1829 | goto Elong; |
1830 | root->mnt = vfsmnt; | ||
1831 | root->dentry = dentry; | ||
1827 | return retval; | 1832 | return retval; |
1828 | Elong: | 1833 | Elong: |
1829 | return ERR_PTR(-ENAMETOOLONG); | 1834 | return ERR_PTR(-ENAMETOOLONG); |
@@ -1846,6 +1851,7 @@ char *d_path(struct path *path, char *buf, int buflen) | |||
1846 | { | 1851 | { |
1847 | char *res; | 1852 | char *res; |
1848 | struct path root; | 1853 | struct path root; |
1854 | struct path tmp; | ||
1849 | 1855 | ||
1850 | /* | 1856 | /* |
1851 | * We have various synthetic filesystems that never get mounted. On | 1857 | * We have various synthetic filesystems that never get mounted. On |
@@ -1862,7 +1868,8 @@ char *d_path(struct path *path, char *buf, int buflen) | |||
1862 | path_get(&root); | 1868 | path_get(&root); |
1863 | read_unlock(¤t->fs->lock); | 1869 | read_unlock(¤t->fs->lock); |
1864 | spin_lock(&dcache_lock); | 1870 | spin_lock(&dcache_lock); |
1865 | res = __d_path(path->dentry, path->mnt, &root, buf, buflen); | 1871 | tmp = root; |
1872 | res = __d_path(path, &tmp, buf, buflen); | ||
1866 | spin_unlock(&dcache_lock); | 1873 | spin_unlock(&dcache_lock); |
1867 | path_put(&root); | 1874 | path_put(&root); |
1868 | return res; | 1875 | return res; |
@@ -1970,9 +1977,10 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size) | |||
1970 | spin_lock(&dcache_lock); | 1977 | spin_lock(&dcache_lock); |
1971 | if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) { | 1978 | if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) { |
1972 | unsigned long len; | 1979 | unsigned long len; |
1980 | struct path tmp = root; | ||
1973 | char * cwd; | 1981 | char * cwd; |
1974 | 1982 | ||
1975 | cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE); | 1983 | cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE); |
1976 | spin_unlock(&dcache_lock); | 1984 | spin_unlock(&dcache_lock); |
1977 | 1985 | ||
1978 | error = PTR_ERR(cwd); | 1986 | error = PTR_ERR(cwd); |
diff --git a/fs/seq_file.c b/fs/seq_file.c index ae59f5a6c5c1..3f54dbd6c49b 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
@@ -393,6 +393,36 @@ int seq_path(struct seq_file *m, struct path *path, char *esc) | |||
393 | EXPORT_SYMBOL(seq_path); | 393 | EXPORT_SYMBOL(seq_path); |
394 | 394 | ||
395 | /* | 395 | /* |
396 | * Same as seq_path, but relative to supplied root. | ||
397 | * | ||
398 | * root may be changed, see __d_path(). | ||
399 | */ | ||
400 | int seq_path_root(struct seq_file *m, struct path *path, struct path *root, | ||
401 | char *esc) | ||
402 | { | ||
403 | int err = -ENAMETOOLONG; | ||
404 | if (m->count < m->size) { | ||
405 | char *s = m->buf + m->count; | ||
406 | char *p; | ||
407 | |||
408 | spin_lock(&dcache_lock); | ||
409 | p = __d_path(path, root, s, m->size - m->count); | ||
410 | spin_unlock(&dcache_lock); | ||
411 | err = PTR_ERR(p); | ||
412 | if (!IS_ERR(p)) { | ||
413 | s = mangle_path(s, p, esc); | ||
414 | if (s) { | ||
415 | p = m->buf + m->count; | ||
416 | m->count = s - m->buf; | ||
417 | return 0; | ||
418 | } | ||
419 | } | ||
420 | } | ||
421 | m->count = m->size; | ||
422 | return err; | ||
423 | } | ||
424 | |||
425 | /* | ||
396 | * returns the path of the 'dentry' from the root of its filesystem. | 426 | * returns the path of the 'dentry' from the root of its filesystem. |
397 | */ | 427 | */ |
398 | int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc) | 428 | int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc) |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 63960033b6f5..cfb1627ac51c 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -301,6 +301,7 @@ extern int d_validate(struct dentry *, struct dentry *); | |||
301 | */ | 301 | */ |
302 | extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...); | 302 | extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...); |
303 | 303 | ||
304 | extern char *__d_path(const struct path *path, struct path *root, char *, int); | ||
304 | extern char *d_path(struct path *, char *, int); | 305 | extern char *d_path(struct path *, char *, int); |
305 | extern char *dentry_path(struct dentry *, char *, int); | 306 | extern char *dentry_path(struct dentry *, char *, int); |
306 | 307 | ||
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 11676ccef7b3..5b5369c3c209 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h | |||
@@ -46,6 +46,8 @@ int seq_printf(struct seq_file *, const char *, ...) | |||
46 | 46 | ||
47 | int seq_path(struct seq_file *, struct path *, char *); | 47 | int seq_path(struct seq_file *, struct path *, char *); |
48 | int seq_dentry(struct seq_file *, struct dentry *, char *); | 48 | int seq_dentry(struct seq_file *, struct dentry *, char *); |
49 | int seq_path_root(struct seq_file *m, struct path *path, struct path *root, | ||
50 | char *esc); | ||
49 | 51 | ||
50 | int single_open(struct file *, int (*)(struct seq_file *, void *), void *); | 52 | int single_open(struct file *, int (*)(struct seq_file *, void *), void *); |
51 | int single_release(struct inode *, struct file *); | 53 | int single_release(struct inode *, struct file *); |