aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/dcache.c24
-rw-r--r--fs/seq_file.c30
-rw-r--r--include/linux/dcache.h1
-rw-r--r--include/linux/seq_file.h2
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 */
1776static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt, 1777char *__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;
1828Elong: 1833Elong:
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(&current->fs->lock); 1869 read_unlock(&current->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)
393EXPORT_SYMBOL(seq_path); 393EXPORT_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 */
400int 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 */
398int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc) 428int 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 */
302extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...); 302extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
303 303
304extern char *__d_path(const struct path *path, struct path *root, char *, int);
304extern char *d_path(struct path *, char *, int); 305extern char *d_path(struct path *, char *, int);
305extern char *dentry_path(struct dentry *, char *, int); 306extern 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
47int seq_path(struct seq_file *, struct path *, char *); 47int seq_path(struct seq_file *, struct path *, char *);
48int seq_dentry(struct seq_file *, struct dentry *, char *); 48int seq_dentry(struct seq_file *, struct dentry *, char *);
49int seq_path_root(struct seq_file *m, struct path *path, struct path *root,
50 char *esc);
49 51
50int single_open(struct file *, int (*)(struct seq_file *, void *), void *); 52int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
51int single_release(struct inode *, struct file *); 53int single_release(struct inode *, struct file *);