aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/kernel/perfmon.c15
-rw-r--r--fs/9p/vfs_inode.c15
-rw-r--r--fs/cachefiles/daemon.c32
-rw-r--r--fs/dcache.c188
-rw-r--r--fs/fs_struct.c7
-rw-r--r--fs/isofs/inode.c7
-rw-r--r--fs/namei.c15
-rw-r--r--fs/namespace.c6
-rw-r--r--fs/proc/base.c24
-rw-r--r--fs/sysv/super.c1
-rw-r--r--include/linux/dcache.h1
-rw-r--r--include/linux/fs_struct.h27
-rw-r--r--include/linux/mount.h1
-rw-r--r--include/linux/path.h5
-rw-r--r--kernel/auditsc.c9
15 files changed, 223 insertions, 130 deletions
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 744329072f33..cce050e85c73 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2191,8 +2191,15 @@ pfmfs_delete_dentry(struct dentry *dentry)
2191 return 1; 2191 return 1;
2192} 2192}
2193 2193
2194static char *pfmfs_dname(struct dentry *dentry, char *buffer, int buflen)
2195{
2196 return dynamic_dname(dentry, buffer, buflen, "pfm:[%lu]",
2197 dentry->d_inode->i_ino);
2198}
2199
2194static const struct dentry_operations pfmfs_dentry_operations = { 2200static const struct dentry_operations pfmfs_dentry_operations = {
2195 .d_delete = pfmfs_delete_dentry, 2201 .d_delete = pfmfs_delete_dentry,
2202 .d_dname = pfmfs_dname,
2196}; 2203};
2197 2204
2198 2205
@@ -2202,8 +2209,7 @@ pfm_alloc_file(pfm_context_t *ctx)
2202 struct file *file; 2209 struct file *file;
2203 struct inode *inode; 2210 struct inode *inode;
2204 struct path path; 2211 struct path path;
2205 char name[32]; 2212 struct qstr this = { .name = "" };
2206 struct qstr this;
2207 2213
2208 /* 2214 /*
2209 * allocate a new inode 2215 * allocate a new inode
@@ -2218,11 +2224,6 @@ pfm_alloc_file(pfm_context_t *ctx)
2218 inode->i_uid = current_fsuid(); 2224 inode->i_uid = current_fsuid();
2219 inode->i_gid = current_fsgid(); 2225 inode->i_gid = current_fsgid();
2220 2226
2221 sprintf(name, "[%lu]", inode->i_ino);
2222 this.name = name;
2223 this.len = strlen(name);
2224 this.hash = inode->i_ino;
2225
2226 /* 2227 /*
2227 * allocate a new dcache entry 2228 * allocate a new dcache entry
2228 */ 2229 */
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index d97c34a24f7a..c7c23eab9440 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1263,10 +1263,19 @@ static int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
1263 return PTR_ERR(fid); 1263 return PTR_ERR(fid);
1264 1264
1265 retval = p9_client_setattr(fid, &p9attr); 1265 retval = p9_client_setattr(fid, &p9attr);
1266 if (retval >= 0) 1266 if (retval < 0)
1267 retval = inode_setattr(dentry->d_inode, iattr); 1267 return retval;
1268 1268
1269 return retval; 1269 if ((iattr->ia_valid & ATTR_SIZE) &&
1270 iattr->ia_size != i_size_read(dentry->d_inode)) {
1271 retval = vmtruncate(dentry->d_inode, iattr->ia_size);
1272 if (retval)
1273 return retval;
1274 }
1275
1276 setattr_copy(dentry->d_inode, iattr);
1277 mark_inode_dirty(dentry->d_inode);
1278 return 0;
1270} 1279}
1271 1280
1272/** 1281/**
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c
index 24eb0d37241a..727caedcdd92 100644
--- a/fs/cachefiles/daemon.c
+++ b/fs/cachefiles/daemon.c
@@ -552,8 +552,7 @@ static int cachefiles_daemon_tag(struct cachefiles_cache *cache, char *args)
552 */ 552 */
553static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args) 553static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)
554{ 554{
555 struct fs_struct *fs; 555 struct path path;
556 struct dentry *dir;
557 const struct cred *saved_cred; 556 const struct cred *saved_cred;
558 int ret; 557 int ret;
559 558
@@ -573,24 +572,21 @@ static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)
573 } 572 }
574 573
575 /* extract the directory dentry from the cwd */ 574 /* extract the directory dentry from the cwd */
576 fs = current->fs; 575 get_fs_pwd(current->fs, &path);
577 read_lock(&fs->lock);
578 dir = dget(fs->pwd.dentry);
579 read_unlock(&fs->lock);
580 576
581 if (!S_ISDIR(dir->d_inode->i_mode)) 577 if (!S_ISDIR(path.dentry->d_inode->i_mode))
582 goto notdir; 578 goto notdir;
583 579
584 cachefiles_begin_secure(cache, &saved_cred); 580 cachefiles_begin_secure(cache, &saved_cred);
585 ret = cachefiles_cull(cache, dir, args); 581 ret = cachefiles_cull(cache, path.dentry, args);
586 cachefiles_end_secure(cache, saved_cred); 582 cachefiles_end_secure(cache, saved_cred);
587 583
588 dput(dir); 584 path_put(&path);
589 _leave(" = %d", ret); 585 _leave(" = %d", ret);
590 return ret; 586 return ret;
591 587
592notdir: 588notdir:
593 dput(dir); 589 path_put(&path);
594 kerror("cull command requires dirfd to be a directory"); 590 kerror("cull command requires dirfd to be a directory");
595 return -ENOTDIR; 591 return -ENOTDIR;
596 592
@@ -628,8 +624,7 @@ inval:
628 */ 624 */
629static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args) 625static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)
630{ 626{
631 struct fs_struct *fs; 627 struct path path;
632 struct dentry *dir;
633 const struct cred *saved_cred; 628 const struct cred *saved_cred;
634 int ret; 629 int ret;
635 630
@@ -649,24 +644,21 @@ static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)
649 } 644 }
650 645
651 /* extract the directory dentry from the cwd */ 646 /* extract the directory dentry from the cwd */
652 fs = current->fs; 647 get_fs_pwd(current->fs, &path);
653 read_lock(&fs->lock);
654 dir = dget(fs->pwd.dentry);
655 read_unlock(&fs->lock);
656 648
657 if (!S_ISDIR(dir->d_inode->i_mode)) 649 if (!S_ISDIR(path.dentry->d_inode->i_mode))
658 goto notdir; 650 goto notdir;
659 651
660 cachefiles_begin_secure(cache, &saved_cred); 652 cachefiles_begin_secure(cache, &saved_cred);
661 ret = cachefiles_check_in_use(cache, dir, args); 653 ret = cachefiles_check_in_use(cache, path.dentry, args);
662 cachefiles_end_secure(cache, saved_cred); 654 cachefiles_end_secure(cache, saved_cred);
663 655
664 dput(dir); 656 path_put(&path);
665 //_leave(" = %d", ret); 657 //_leave(" = %d", ret);
666 return ret; 658 return ret;
667 659
668notdir: 660notdir:
669 dput(dir); 661 path_put(&path);
670 kerror("inuse command requires dirfd to be a directory"); 662 kerror("inuse command requires dirfd to be a directory");
671 return -ENOTDIR; 663 return -ENOTDIR;
672 664
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) {
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index eee059052db5..1ee40eb9a2c0 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -106,12 +106,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old)
106 fs->in_exec = 0; 106 fs->in_exec = 0;
107 rwlock_init(&fs->lock); 107 rwlock_init(&fs->lock);
108 fs->umask = old->umask; 108 fs->umask = old->umask;
109 read_lock(&old->lock); 109 get_fs_root_and_pwd(old, &fs->root, &fs->pwd);
110 fs->root = old->root;
111 path_get(&old->root);
112 fs->pwd = old->pwd;
113 path_get(&old->pwd);
114 read_unlock(&old->lock);
115 } 110 }
116 return fs; 111 return fs;
117} 112}
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 6b4dcd4f2943..5a44811b5027 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -722,7 +722,12 @@ root_found:
722 } 722 }
723 723
724 s->s_magic = ISOFS_SUPER_MAGIC; 724 s->s_magic = ISOFS_SUPER_MAGIC;
725 s->s_maxbytes = 0xffffffff; /* We can handle files up to 4 GB */ 725
726 /*
727 * With multi-extent files, file size is only limited by the maximum
728 * size of a file system, which is 8 TB.
729 */
730 s->s_maxbytes = 0x80000000000LL;
726 731
727 /* 732 /*
728 * The CDROM is read-only, has no nodes (devices) on it, and since 733 * The CDROM is read-only, has no nodes (devices) on it, and since
diff --git a/fs/namei.c b/fs/namei.c
index 13ff4abdbdca..17ea76bf2fbe 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -483,13 +483,8 @@ ok:
483 483
484static __always_inline void set_root(struct nameidata *nd) 484static __always_inline void set_root(struct nameidata *nd)
485{ 485{
486 if (!nd->root.mnt) { 486 if (!nd->root.mnt)
487 struct fs_struct *fs = current->fs; 487 get_fs_root(current->fs, &nd->root);
488 read_lock(&fs->lock);
489 nd->root = fs->root;
490 path_get(&nd->root);
491 read_unlock(&fs->lock);
492 }
493} 488}
494 489
495static int link_path_walk(const char *, struct nameidata *); 490static int link_path_walk(const char *, struct nameidata *);
@@ -1015,11 +1010,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, struct namei
1015 nd->path = nd->root; 1010 nd->path = nd->root;
1016 path_get(&nd->root); 1011 path_get(&nd->root);
1017 } else if (dfd == AT_FDCWD) { 1012 } else if (dfd == AT_FDCWD) {
1018 struct fs_struct *fs = current->fs; 1013 get_fs_pwd(current->fs, &nd->path);
1019 read_lock(&fs->lock);
1020 nd->path = fs->pwd;
1021 path_get(&fs->pwd);
1022 read_unlock(&fs->lock);
1023 } else { 1014 } else {
1024 struct dentry *dentry; 1015 struct dentry *dentry;
1025 1016
diff --git a/fs/namespace.c b/fs/namespace.c
index 66c4f7e781cb..2e10cb19c5b0 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -788,7 +788,6 @@ static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt)
788 { MNT_NOATIME, ",noatime" }, 788 { MNT_NOATIME, ",noatime" },
789 { MNT_NODIRATIME, ",nodiratime" }, 789 { MNT_NODIRATIME, ",nodiratime" },
790 { MNT_RELATIME, ",relatime" }, 790 { MNT_RELATIME, ",relatime" },
791 { MNT_STRICTATIME, ",strictatime" },
792 { 0, NULL } 791 { 0, NULL }
793 }; 792 };
794 const struct proc_fs_info *fs_infop; 793 const struct proc_fs_info *fs_infop;
@@ -2213,10 +2212,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
2213 goto out1; 2212 goto out1;
2214 } 2213 }
2215 2214
2216 read_lock(&current->fs->lock); 2215 get_fs_root(current->fs, &root);
2217 root = current->fs->root;
2218 path_get(&current->fs->root);
2219 read_unlock(&current->fs->lock);
2220 down_write(&namespace_sem); 2216 down_write(&namespace_sem);
2221 mutex_lock(&old.dentry->d_inode->i_mutex); 2217 mutex_lock(&old.dentry->d_inode->i_mutex);
2222 error = -EINVAL; 2218 error = -EINVAL;
diff --git a/fs/proc/base.c b/fs/proc/base.c
index c806dfb24e08..a1c43e7c8a7b 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -149,18 +149,13 @@ static unsigned int pid_entry_count_dirs(const struct pid_entry *entries,
149 return count; 149 return count;
150} 150}
151 151
152static int get_fs_path(struct task_struct *task, struct path *path, bool root) 152static int get_task_root(struct task_struct *task, struct path *root)
153{ 153{
154 struct fs_struct *fs;
155 int result = -ENOENT; 154 int result = -ENOENT;
156 155
157 task_lock(task); 156 task_lock(task);
158 fs = task->fs; 157 if (task->fs) {
159 if (fs) { 158 get_fs_root(task->fs, root);
160 read_lock(&fs->lock);
161 *path = root ? fs->root : fs->pwd;
162 path_get(path);
163 read_unlock(&fs->lock);
164 result = 0; 159 result = 0;
165 } 160 }
166 task_unlock(task); 161 task_unlock(task);
@@ -173,7 +168,12 @@ static int proc_cwd_link(struct inode *inode, struct path *path)
173 int result = -ENOENT; 168 int result = -ENOENT;
174 169
175 if (task) { 170 if (task) {
176 result = get_fs_path(task, path, 0); 171 task_lock(task);
172 if (task->fs) {
173 get_fs_pwd(task->fs, path);
174 result = 0;
175 }
176 task_unlock(task);
177 put_task_struct(task); 177 put_task_struct(task);
178 } 178 }
179 return result; 179 return result;
@@ -185,7 +185,7 @@ static int proc_root_link(struct inode *inode, struct path *path)
185 int result = -ENOENT; 185 int result = -ENOENT;
186 186
187 if (task) { 187 if (task) {
188 result = get_fs_path(task, path, 1); 188 result = get_task_root(task, path);
189 put_task_struct(task); 189 put_task_struct(task);
190 } 190 }
191 return result; 191 return result;
@@ -597,7 +597,7 @@ static int mounts_open_common(struct inode *inode, struct file *file,
597 get_mnt_ns(ns); 597 get_mnt_ns(ns);
598 } 598 }
599 rcu_read_unlock(); 599 rcu_read_unlock();
600 if (ns && get_fs_path(task, &root, 1) == 0) 600 if (ns && get_task_root(task, &root) == 0)
601 ret = 0; 601 ret = 0;
602 put_task_struct(task); 602 put_task_struct(task);
603 } 603 }
@@ -1526,7 +1526,7 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen)
1526 if (!tmp) 1526 if (!tmp)
1527 return -ENOMEM; 1527 return -ENOMEM;
1528 1528
1529 pathname = d_path(path, tmp, PAGE_SIZE); 1529 pathname = d_path_with_unreachable(path, tmp, PAGE_SIZE);
1530 len = PTR_ERR(pathname); 1530 len = PTR_ERR(pathname);
1531 if (IS_ERR(pathname)) 1531 if (IS_ERR(pathname))
1532 goto out; 1532 goto out;
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index 85359a8df605..a0b0cda6927e 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -24,7 +24,6 @@
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/buffer_head.h> 26#include <linux/buffer_head.h>
27#include <linux/parser.h>
28#include "sysv.h" 27#include "sysv.h"
29 28
30/* 29/*
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index d23be0386e2d..6a4aea30aa09 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -315,6 +315,7 @@ extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
315 315
316extern char *__d_path(const struct path *path, struct path *root, char *, int); 316extern char *__d_path(const struct path *path, struct path *root, char *, int);
317extern char *d_path(const struct path *, char *, int); 317extern char *d_path(const struct path *, char *, int);
318extern char *d_path_with_unreachable(const struct path *, char *, int);
318extern char *__dentry_path(struct dentry *, char *, int); 319extern char *__dentry_path(struct dentry *, char *, int);
319extern char *dentry_path(struct dentry *, char *, int); 320extern char *dentry_path(struct dentry *, char *, int);
320 321
diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h
index 78a05bfcd8eb..eca3d5202138 100644
--- a/include/linux/fs_struct.h
+++ b/include/linux/fs_struct.h
@@ -21,4 +21,31 @@ extern void free_fs_struct(struct fs_struct *);
21extern void daemonize_fs_struct(void); 21extern void daemonize_fs_struct(void);
22extern int unshare_fs_struct(void); 22extern int unshare_fs_struct(void);
23 23
24static inline void get_fs_root(struct fs_struct *fs, struct path *root)
25{
26 read_lock(&fs->lock);
27 *root = fs->root;
28 path_get(root);
29 read_unlock(&fs->lock);
30}
31
32static inline void get_fs_pwd(struct fs_struct *fs, struct path *pwd)
33{
34 read_lock(&fs->lock);
35 *pwd = fs->pwd;
36 path_get(pwd);
37 read_unlock(&fs->lock);
38}
39
40static inline void get_fs_root_and_pwd(struct fs_struct *fs, struct path *root,
41 struct path *pwd)
42{
43 read_lock(&fs->lock);
44 *root = fs->root;
45 path_get(root);
46 *pwd = fs->pwd;
47 path_get(pwd);
48 read_unlock(&fs->lock);
49}
50
24#endif /* _LINUX_FS_STRUCT_H */ 51#endif /* _LINUX_FS_STRUCT_H */
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 907210bd9f9c..5e7a59408dd4 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -27,7 +27,6 @@ struct mnt_namespace;
27#define MNT_NODIRATIME 0x10 27#define MNT_NODIRATIME 0x10
28#define MNT_RELATIME 0x20 28#define MNT_RELATIME 0x20
29#define MNT_READONLY 0x40 /* does the user want this to be r/o? */ 29#define MNT_READONLY 0x40 /* does the user want this to be r/o? */
30#define MNT_STRICTATIME 0x80
31 30
32#define MNT_SHRINKABLE 0x100 31#define MNT_SHRINKABLE 0x100
33#define MNT_WRITE_HOLD 0x200 32#define MNT_WRITE_HOLD 0x200
diff --git a/include/linux/path.h b/include/linux/path.h
index 915e0c382a51..edc98dec6266 100644
--- a/include/linux/path.h
+++ b/include/linux/path.h
@@ -12,4 +12,9 @@ struct path {
12extern void path_get(struct path *); 12extern void path_get(struct path *);
13extern void path_put(struct path *); 13extern void path_put(struct path *);
14 14
15static inline int path_equal(const struct path *path1, const struct path *path2)
16{
17 return path1->mnt == path2->mnt && path1->dentry == path2->dentry;
18}
19
15#endif /* _LINUX_PATH_H */ 20#endif /* _LINUX_PATH_H */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index b87a63beb66c..1b31c130d034 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1835,13 +1835,8 @@ void __audit_getname(const char *name)
1835 context->names[context->name_count].ino = (unsigned long)-1; 1835 context->names[context->name_count].ino = (unsigned long)-1;
1836 context->names[context->name_count].osid = 0; 1836 context->names[context->name_count].osid = 0;
1837 ++context->name_count; 1837 ++context->name_count;
1838 if (!context->pwd.dentry) { 1838 if (!context->pwd.dentry)
1839 read_lock(&current->fs->lock); 1839 get_fs_pwd(current->fs, &context->pwd);
1840 context->pwd = current->fs->pwd;
1841 path_get(&current->fs->pwd);
1842 read_unlock(&current->fs->lock);
1843 }
1844
1845} 1840}
1846 1841
1847/* audit_putname - intercept a putname request 1842/* audit_putname - intercept a putname request