aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c188
1 files changed, 133 insertions, 55 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 9f2c13417969..166d35d56868 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1905,48 +1905,30 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name)
1905} 1905}
1906 1906
1907/** 1907/**
1908 * __d_path - return the path of a dentry 1908 * Prepend path string to a buffer
1909 *
1909 * @path: the dentry/vfsmount to report 1910 * @path: the dentry/vfsmount to report
1910 * @root: root vfsmnt/dentry (may be modified by this function) 1911 * @root: root vfsmnt/dentry (may be modified by this function)
1911 * @buffer: buffer to return value in 1912 * @buffer: pointer to the end of the buffer
1912 * @buflen: buffer length 1913 * @buflen: pointer to buffer length
1913 * 1914 *
1914 * Convert a dentry into an ASCII path name. If the entry has been deleted 1915 * Caller holds the dcache_lock.
1915 * the string " (deleted)" is appended. Note that this is ambiguous.
1916 *
1917 * Returns a pointer into the buffer or an error code if the
1918 * path was too long.
1919 *
1920 * "buflen" should be positive. Caller holds the dcache_lock.
1921 * 1916 *
1922 * If path is not reachable from the supplied root, then the value of 1917 * If path is not reachable from the supplied root, then the value of
1923 * root is changed (without modifying refcounts). 1918 * root is changed (without modifying refcounts).
1924 */ 1919 */
1925char *__d_path(const struct path *path, struct path *root, 1920static int prepend_path(const struct path *path, struct path *root,
1926 char *buffer, int buflen) 1921 char **buffer, int *buflen)
1927{ 1922{
1928 struct dentry *dentry = path->dentry; 1923 struct dentry *dentry = path->dentry;
1929 struct vfsmount *vfsmnt = path->mnt; 1924 struct vfsmount *vfsmnt = path->mnt;
1930 char *end = buffer + buflen; 1925 bool slash = false;
1931 char *retval; 1926 int error = 0;
1932 1927
1933 spin_lock(&vfsmount_lock); 1928 spin_lock(&vfsmount_lock);
1934 prepend(&end, &buflen, "\0", 1); 1929 while (dentry != root->dentry || vfsmnt != root->mnt) {
1935 if (d_unlinked(dentry) &&
1936 (prepend(&end, &buflen, " (deleted)", 10) != 0))
1937 goto Elong;
1938
1939 if (buflen < 1)
1940 goto Elong;
1941 /* Get '/' right */
1942 retval = end-1;
1943 *retval = '/';
1944
1945 for (;;) {
1946 struct dentry * parent; 1930 struct dentry * parent;
1947 1931
1948 if (dentry == root->dentry && vfsmnt == root->mnt)
1949 break;
1950 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { 1932 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
1951 /* Global root? */ 1933 /* Global root? */
1952 if (vfsmnt->mnt_parent == vfsmnt) { 1934 if (vfsmnt->mnt_parent == vfsmnt) {
@@ -1958,28 +1940,88 @@ char *__d_path(const struct path *path, struct path *root,
1958 } 1940 }
1959 parent = dentry->d_parent; 1941 parent = dentry->d_parent;
1960 prefetch(parent); 1942 prefetch(parent);
1961 if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) || 1943 error = prepend_name(buffer, buflen, &dentry->d_name);
1962 (prepend(&end, &buflen, "/", 1) != 0)) 1944 if (!error)
1963 goto Elong; 1945 error = prepend(buffer, buflen, "/", 1);
1964 retval = end; 1946 if (error)
1947 break;
1948
1949 slash = true;
1965 dentry = parent; 1950 dentry = parent;
1966 } 1951 }
1967 1952
1968out: 1953out:
1954 if (!error && !slash)
1955 error = prepend(buffer, buflen, "/", 1);
1956
1969 spin_unlock(&vfsmount_lock); 1957 spin_unlock(&vfsmount_lock);
1970 return retval; 1958 return error;
1971 1959
1972global_root: 1960global_root:
1973 retval += 1; /* hit the slash */ 1961 /*
1974 if (prepend_name(&retval, &buflen, &dentry->d_name) != 0) 1962 * Filesystems needing to implement special "root names"
1975 goto Elong; 1963 * should do so with ->d_dname()
1964 */
1965 if (IS_ROOT(dentry) &&
1966 (dentry->d_name.len != 1 || dentry->d_name.name[0] != '/')) {
1967 WARN(1, "Root dentry has weird name <%.*s>\n",
1968 (int) dentry->d_name.len, dentry->d_name.name);
1969 }
1976 root->mnt = vfsmnt; 1970 root->mnt = vfsmnt;
1977 root->dentry = dentry; 1971 root->dentry = dentry;
1978 goto out; 1972 goto out;
1973}
1979 1974
1980Elong: 1975/**
1981 retval = ERR_PTR(-ENAMETOOLONG); 1976 * __d_path - return the path of a dentry
1982 goto out; 1977 * @path: the dentry/vfsmount to report
1978 * @root: root vfsmnt/dentry (may be modified by this function)
1979 * @buffer: buffer to return value in
1980 * @buflen: buffer length
1981 *
1982 * Convert a dentry into an ASCII path name.
1983 *
1984 * Returns a pointer into the buffer or an error code if the
1985 * path was too long.
1986 *
1987 * "buflen" should be positive. Caller holds the dcache_lock.
1988 *
1989 * If path is not reachable from the supplied root, then the value of
1990 * root is changed (without modifying refcounts).
1991 */
1992char *__d_path(const struct path *path, struct path *root,
1993 char *buf, int buflen)
1994{
1995 char *res = buf + buflen;
1996 int error;
1997
1998 prepend(&res, &buflen, "\0", 1);
1999 error = prepend_path(path, root, &res, &buflen);
2000 if (error)
2001 return ERR_PTR(error);
2002
2003 return res;
2004}
2005
2006/*
2007 * same as __d_path but appends "(deleted)" for unlinked files.
2008 */
2009static int path_with_deleted(const struct path *path, struct path *root,
2010 char **buf, int *buflen)
2011{
2012 prepend(buf, buflen, "\0", 1);
2013 if (d_unlinked(path->dentry)) {
2014 int error = prepend(buf, buflen, " (deleted)", 10);
2015 if (error)
2016 return error;
2017 }
2018
2019 return prepend_path(path, root, buf, buflen);
2020}
2021
2022static int prepend_unreachable(char **buffer, int *buflen)
2023{
2024 return prepend(buffer, buflen, "(unreachable)", 13);
1983} 2025}
1984 2026
1985/** 2027/**
@@ -2000,9 +2042,10 @@ Elong:
2000 */ 2042 */
2001char *d_path(const struct path *path, char *buf, int buflen) 2043char *d_path(const struct path *path, char *buf, int buflen)
2002{ 2044{
2003 char *res; 2045 char *res = buf + buflen;
2004 struct path root; 2046 struct path root;
2005 struct path tmp; 2047 struct path tmp;
2048 int error;
2006 2049
2007 /* 2050 /*
2008 * We have various synthetic filesystems that never get mounted. On 2051 * We have various synthetic filesystems that never get mounted. On
@@ -2014,19 +2057,51 @@ char *d_path(const struct path *path, char *buf, int buflen)
2014 if (path->dentry->d_op && path->dentry->d_op->d_dname) 2057 if (path->dentry->d_op && path->dentry->d_op->d_dname)
2015 return path->dentry->d_op->d_dname(path->dentry, buf, buflen); 2058 return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
2016 2059
2017 read_lock(&current->fs->lock); 2060 get_fs_root(current->fs, &root);
2018 root = current->fs->root;
2019 path_get(&root);
2020 read_unlock(&current->fs->lock);
2021 spin_lock(&dcache_lock); 2061 spin_lock(&dcache_lock);
2022 tmp = root; 2062 tmp = root;
2023 res = __d_path(path, &tmp, buf, buflen); 2063 error = path_with_deleted(path, &tmp, &res, &buflen);
2064 if (error)
2065 res = ERR_PTR(error);
2024 spin_unlock(&dcache_lock); 2066 spin_unlock(&dcache_lock);
2025 path_put(&root); 2067 path_put(&root);
2026 return res; 2068 return res;
2027} 2069}
2028EXPORT_SYMBOL(d_path); 2070EXPORT_SYMBOL(d_path);
2029 2071
2072/**
2073 * d_path_with_unreachable - return the path of a dentry
2074 * @path: path to report
2075 * @buf: buffer to return value in
2076 * @buflen: buffer length
2077 *
2078 * The difference from d_path() is that this prepends "(unreachable)"
2079 * to paths which are unreachable from the current process' root.
2080 */
2081char *d_path_with_unreachable(const struct path *path, char *buf, int buflen)
2082{
2083 char *res = buf + buflen;
2084 struct path root;
2085 struct path tmp;
2086 int error;
2087
2088 if (path->dentry->d_op && path->dentry->d_op->d_dname)
2089 return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
2090
2091 get_fs_root(current->fs, &root);
2092 spin_lock(&dcache_lock);
2093 tmp = root;
2094 error = path_with_deleted(path, &tmp, &res, &buflen);
2095 if (!error && !path_equal(&tmp, &root))
2096 error = prepend_unreachable(&res, &buflen);
2097 spin_unlock(&dcache_lock);
2098 path_put(&root);
2099 if (error)
2100 res = ERR_PTR(error);
2101
2102 return res;
2103}
2104
2030/* 2105/*
2031 * Helper function for dentry_operations.d_dname() members 2106 * Helper function for dentry_operations.d_dname() members
2032 */ 2107 */
@@ -2129,27 +2204,30 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
2129 if (!page) 2204 if (!page)
2130 return -ENOMEM; 2205 return -ENOMEM;
2131 2206
2132 read_lock(&current->fs->lock); 2207 get_fs_root_and_pwd(current->fs, &root, &pwd);
2133 pwd = current->fs->pwd;
2134 path_get(&pwd);
2135 root = current->fs->root;
2136 path_get(&root);
2137 read_unlock(&current->fs->lock);
2138 2208
2139 error = -ENOENT; 2209 error = -ENOENT;
2140 spin_lock(&dcache_lock); 2210 spin_lock(&dcache_lock);
2141 if (!d_unlinked(pwd.dentry)) { 2211 if (!d_unlinked(pwd.dentry)) {
2142 unsigned long len; 2212 unsigned long len;
2143 struct path tmp = root; 2213 struct path tmp = root;
2144 char * cwd; 2214 char *cwd = page + PAGE_SIZE;
2215 int buflen = PAGE_SIZE;
2145 2216
2146 cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE); 2217 prepend(&cwd, &buflen, "\0", 1);
2218 error = prepend_path(&pwd, &tmp, &cwd, &buflen);
2147 spin_unlock(&dcache_lock); 2219 spin_unlock(&dcache_lock);
2148 2220
2149 error = PTR_ERR(cwd); 2221 if (error)
2150 if (IS_ERR(cwd))
2151 goto out; 2222 goto out;
2152 2223
2224 /* Unreachable from current root */
2225 if (!path_equal(&tmp, &root)) {
2226 error = prepend_unreachable(&cwd, &buflen);
2227 if (error)
2228 goto out;
2229 }
2230
2153 error = -ERANGE; 2231 error = -ERANGE;
2154 len = PAGE_SIZE + page - cwd; 2232 len = PAGE_SIZE + page - cwd;
2155 if (len <= size) { 2233 if (len <= size) {