aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c114
1 files changed, 82 insertions, 32 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 43455776711e..3ee588d5f585 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1746,12 +1746,21 @@ shouldnt_be_hashed:
1746 goto shouldnt_be_hashed; 1746 goto shouldnt_be_hashed;
1747} 1747}
1748 1748
1749static int prepend(char **buffer, int *buflen, const char *str,
1750 int namelen)
1751{
1752 *buflen -= namelen;
1753 if (*buflen < 0)
1754 return -ENAMETOOLONG;
1755 *buffer -= namelen;
1756 memcpy(*buffer, str, namelen);
1757 return 0;
1758}
1759
1749/** 1760/**
1750 * d_path - return the path of a dentry 1761 * d_path - return the path of a dentry
1751 * @dentry: dentry to report 1762 * @path: the dentry/vfsmount to report
1752 * @vfsmnt: vfsmnt to which the dentry belongs 1763 * @root: root vfsmnt/dentry (may be modified by this function)
1753 * @root: root dentry
1754 * @rootmnt: vfsmnt to which the root dentry belongs
1755 * @buffer: buffer to return value in 1764 * @buffer: buffer to return value in
1756 * @buflen: buffer length 1765 * @buflen: buffer length
1757 * 1766 *
@@ -1761,23 +1770,22 @@ shouldnt_be_hashed:
1761 * 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.
1762 * 1771 *
1763 * "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).
1764 */ 1776 */
1765static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt, 1777char *__d_path(const struct path *path, struct path *root,
1766 struct path *root, char *buffer, int buflen) 1778 char *buffer, int buflen)
1767{ 1779{
1780 struct dentry *dentry = path->dentry;
1781 struct vfsmount *vfsmnt = path->mnt;
1768 char * end = buffer+buflen; 1782 char * end = buffer+buflen;
1769 char * retval; 1783 char * retval;
1770 int namelen; 1784
1771 1785 prepend(&end, &buflen, "\0", 1);
1772 *--end = '\0'; 1786 if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
1773 buflen--; 1787 (prepend(&end, &buflen, " (deleted)", 10) != 0))
1774 if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
1775 buflen -= 10;
1776 end -= 10;
1777 if (buflen < 0)
1778 goto Elong; 1788 goto Elong;
1779 memcpy(end, " (deleted)", 10);
1780 }
1781 1789
1782 if (buflen < 1) 1790 if (buflen < 1)
1783 goto Elong; 1791 goto Elong;
@@ -1804,13 +1812,10 @@ static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
1804 } 1812 }
1805 parent = dentry->d_parent; 1813 parent = dentry->d_parent;
1806 prefetch(parent); 1814 prefetch(parent);
1807 namelen = dentry->d_name.len; 1815 if ((prepend(&end, &buflen, dentry->d_name.name,
1808 buflen -= namelen + 1; 1816 dentry->d_name.len) != 0) ||
1809 if (buflen < 0) 1817 (prepend(&end, &buflen, "/", 1) != 0))
1810 goto Elong; 1818 goto Elong;
1811 end -= namelen;
1812 memcpy(end, dentry->d_name.name, namelen);
1813 *--end = '/';
1814 retval = end; 1819 retval = end;
1815 dentry = parent; 1820 dentry = parent;
1816 } 1821 }
@@ -1818,12 +1823,12 @@ static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
1818 return retval; 1823 return retval;
1819 1824
1820global_root: 1825global_root:
1821 namelen = dentry->d_name.len; 1826 retval += 1; /* hit the slash */
1822 buflen -= namelen; 1827 if (prepend(&retval, &buflen, dentry->d_name.name,
1823 if (buflen < 0) 1828 dentry->d_name.len) != 0)
1824 goto Elong; 1829 goto Elong;
1825 retval -= namelen-1; /* hit the slash */ 1830 root->mnt = vfsmnt;
1826 memcpy(retval, dentry->d_name.name, namelen); 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
@@ -1859,10 +1865,11 @@ char *d_path(struct path *path, char *buf, int buflen)
1859 1865
1860 read_lock(&current->fs->lock); 1866 read_lock(&current->fs->lock);
1861 root = current->fs->root; 1867 root = current->fs->root;
1862 path_get(&current->fs->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;
@@ -1890,6 +1897,48 @@ char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
1890} 1897}
1891 1898
1892/* 1899/*
1900 * Write full pathname from the root of the filesystem into the buffer.
1901 */
1902char *dentry_path(struct dentry *dentry, char *buf, int buflen)
1903{
1904 char *end = buf + buflen;
1905 char *retval;
1906
1907 spin_lock(&dcache_lock);
1908 prepend(&end, &buflen, "\0", 1);
1909 if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
1910 (prepend(&end, &buflen, "//deleted", 9) != 0))
1911 goto Elong;
1912 if (buflen < 1)
1913 goto Elong;
1914 /* Get '/' right */
1915 retval = end-1;
1916 *retval = '/';
1917
1918 for (;;) {
1919 struct dentry *parent;
1920 if (IS_ROOT(dentry))
1921 break;
1922
1923 parent = dentry->d_parent;
1924 prefetch(parent);
1925
1926 if ((prepend(&end, &buflen, dentry->d_name.name,
1927 dentry->d_name.len) != 0) ||
1928 (prepend(&end, &buflen, "/", 1) != 0))
1929 goto Elong;
1930
1931 retval = end;
1932 dentry = parent;
1933 }
1934 spin_unlock(&dcache_lock);
1935 return retval;
1936Elong:
1937 spin_unlock(&dcache_lock);
1938 return ERR_PTR(-ENAMETOOLONG);
1939}
1940
1941/*
1893 * NOTE! The user-level library version returns a 1942 * NOTE! The user-level library version returns a
1894 * character pointer. The kernel system call just 1943 * character pointer. The kernel system call just
1895 * returns the length of the buffer filled (which 1944 * returns the length of the buffer filled (which
@@ -1918,9 +1967,9 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
1918 1967
1919 read_lock(&current->fs->lock); 1968 read_lock(&current->fs->lock);
1920 pwd = current->fs->pwd; 1969 pwd = current->fs->pwd;
1921 path_get(&current->fs->pwd); 1970 path_get(&pwd);
1922 root = current->fs->root; 1971 root = current->fs->root;
1923 path_get(&current->fs->root); 1972 path_get(&root);
1924 read_unlock(&current->fs->lock); 1973 read_unlock(&current->fs->lock);
1925 1974
1926 error = -ENOENT; 1975 error = -ENOENT;
@@ -1928,9 +1977,10 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
1928 spin_lock(&dcache_lock); 1977 spin_lock(&dcache_lock);
1929 if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) { 1978 if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) {
1930 unsigned long len; 1979 unsigned long len;
1980 struct path tmp = root;
1931 char * cwd; 1981 char * cwd;
1932 1982
1933 cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE); 1983 cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
1934 spin_unlock(&dcache_lock); 1984 spin_unlock(&dcache_lock);
1935 1985
1936 error = PTR_ERR(cwd); 1986 error = PTR_ERR(cwd);