aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-10-02 08:45:08 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-10-02 08:45:08 -0400
commit59458f40e25915a355d8b1d701425fe9f4f9ea23 (patch)
treef1c9a2934df686e36d75f759ab7313b6f0e0e5f9 /fs/namei.c
parent825f9075d74028d11d7f5932f04e1b5db3022b51 (diff)
parentd834c16516d1ebec4766fc58c059bf01311e6045 (diff)
Merge branch 'master' into gfs2
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c209
1 files changed, 117 insertions, 92 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 808e4ea2bb94..28d49b301d55 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -518,18 +518,20 @@ static int __emul_lookup_dentry(const char *, struct nameidata *);
518static __always_inline int 518static __always_inline int
519walk_init_root(const char *name, struct nameidata *nd) 519walk_init_root(const char *name, struct nameidata *nd)
520{ 520{
521 read_lock(&current->fs->lock); 521 struct fs_struct *fs = current->fs;
522 if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) { 522
523 nd->mnt = mntget(current->fs->altrootmnt); 523 read_lock(&fs->lock);
524 nd->dentry = dget(current->fs->altroot); 524 if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
525 read_unlock(&current->fs->lock); 525 nd->mnt = mntget(fs->altrootmnt);
526 nd->dentry = dget(fs->altroot);
527 read_unlock(&fs->lock);
526 if (__emul_lookup_dentry(name,nd)) 528 if (__emul_lookup_dentry(name,nd))
527 return 0; 529 return 0;
528 read_lock(&current->fs->lock); 530 read_lock(&fs->lock);
529 } 531 }
530 nd->mnt = mntget(current->fs->rootmnt); 532 nd->mnt = mntget(fs->rootmnt);
531 nd->dentry = dget(current->fs->root); 533 nd->dentry = dget(fs->root);
532 read_unlock(&current->fs->lock); 534 read_unlock(&fs->lock);
533 return 1; 535 return 1;
534} 536}
535 537
@@ -724,17 +726,19 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry)
724 726
725static __always_inline void follow_dotdot(struct nameidata *nd) 727static __always_inline void follow_dotdot(struct nameidata *nd)
726{ 728{
729 struct fs_struct *fs = current->fs;
730
727 while(1) { 731 while(1) {
728 struct vfsmount *parent; 732 struct vfsmount *parent;
729 struct dentry *old = nd->dentry; 733 struct dentry *old = nd->dentry;
730 734
731 read_lock(&current->fs->lock); 735 read_lock(&fs->lock);
732 if (nd->dentry == current->fs->root && 736 if (nd->dentry == fs->root &&
733 nd->mnt == current->fs->rootmnt) { 737 nd->mnt == fs->rootmnt) {
734 read_unlock(&current->fs->lock); 738 read_unlock(&fs->lock);
735 break; 739 break;
736 } 740 }
737 read_unlock(&current->fs->lock); 741 read_unlock(&fs->lock);
738 spin_lock(&dcache_lock); 742 spin_lock(&dcache_lock);
739 if (nd->dentry != nd->mnt->mnt_root) { 743 if (nd->dentry != nd->mnt->mnt_root) {
740 nd->dentry = dget(nd->dentry->d_parent); 744 nd->dentry = dget(nd->dentry->d_parent);
@@ -1042,15 +1046,17 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
1042 struct vfsmount *old_mnt = nd->mnt; 1046 struct vfsmount *old_mnt = nd->mnt;
1043 struct qstr last = nd->last; 1047 struct qstr last = nd->last;
1044 int last_type = nd->last_type; 1048 int last_type = nd->last_type;
1049 struct fs_struct *fs = current->fs;
1050
1045 /* 1051 /*
1046 * NAME was not found in alternate root or it's a directory. Try to find 1052 * NAME was not found in alternate root or it's a directory.
1047 * it in the normal root: 1053 * Try to find it in the normal root:
1048 */ 1054 */
1049 nd->last_type = LAST_ROOT; 1055 nd->last_type = LAST_ROOT;
1050 read_lock(&current->fs->lock); 1056 read_lock(&fs->lock);
1051 nd->mnt = mntget(current->fs->rootmnt); 1057 nd->mnt = mntget(fs->rootmnt);
1052 nd->dentry = dget(current->fs->root); 1058 nd->dentry = dget(fs->root);
1053 read_unlock(&current->fs->lock); 1059 read_unlock(&fs->lock);
1054 if (path_walk(name, nd) == 0) { 1060 if (path_walk(name, nd) == 0) {
1055 if (nd->dentry->d_inode) { 1061 if (nd->dentry->d_inode) {
1056 dput(old_dentry); 1062 dput(old_dentry);
@@ -1074,6 +1080,7 @@ void set_fs_altroot(void)
1074 struct vfsmount *mnt = NULL, *oldmnt; 1080 struct vfsmount *mnt = NULL, *oldmnt;
1075 struct dentry *dentry = NULL, *olddentry; 1081 struct dentry *dentry = NULL, *olddentry;
1076 int err; 1082 int err;
1083 struct fs_struct *fs = current->fs;
1077 1084
1078 if (!emul) 1085 if (!emul)
1079 goto set_it; 1086 goto set_it;
@@ -1083,12 +1090,12 @@ void set_fs_altroot(void)
1083 dentry = nd.dentry; 1090 dentry = nd.dentry;
1084 } 1091 }
1085set_it: 1092set_it:
1086 write_lock(&current->fs->lock); 1093 write_lock(&fs->lock);
1087 oldmnt = current->fs->altrootmnt; 1094 oldmnt = fs->altrootmnt;
1088 olddentry = current->fs->altroot; 1095 olddentry = fs->altroot;
1089 current->fs->altrootmnt = mnt; 1096 fs->altrootmnt = mnt;
1090 current->fs->altroot = dentry; 1097 fs->altroot = dentry;
1091 write_unlock(&current->fs->lock); 1098 write_unlock(&fs->lock);
1092 if (olddentry) { 1099 if (olddentry) {
1093 dput(olddentry); 1100 dput(olddentry);
1094 mntput(oldmnt); 1101 mntput(oldmnt);
@@ -1102,29 +1109,30 @@ static int fastcall do_path_lookup(int dfd, const char *name,
1102 int retval = 0; 1109 int retval = 0;
1103 int fput_needed; 1110 int fput_needed;
1104 struct file *file; 1111 struct file *file;
1112 struct fs_struct *fs = current->fs;
1105 1113
1106 nd->last_type = LAST_ROOT; /* if there are only slashes... */ 1114 nd->last_type = LAST_ROOT; /* if there are only slashes... */
1107 nd->flags = flags; 1115 nd->flags = flags;
1108 nd->depth = 0; 1116 nd->depth = 0;
1109 1117
1110 if (*name=='/') { 1118 if (*name=='/') {
1111 read_lock(&current->fs->lock); 1119 read_lock(&fs->lock);
1112 if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) { 1120 if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
1113 nd->mnt = mntget(current->fs->altrootmnt); 1121 nd->mnt = mntget(fs->altrootmnt);
1114 nd->dentry = dget(current->fs->altroot); 1122 nd->dentry = dget(fs->altroot);
1115 read_unlock(&current->fs->lock); 1123 read_unlock(&fs->lock);
1116 if (__emul_lookup_dentry(name,nd)) 1124 if (__emul_lookup_dentry(name,nd))
1117 goto out; /* found in altroot */ 1125 goto out; /* found in altroot */
1118 read_lock(&current->fs->lock); 1126 read_lock(&fs->lock);
1119 } 1127 }
1120 nd->mnt = mntget(current->fs->rootmnt); 1128 nd->mnt = mntget(fs->rootmnt);
1121 nd->dentry = dget(current->fs->root); 1129 nd->dentry = dget(fs->root);
1122 read_unlock(&current->fs->lock); 1130 read_unlock(&fs->lock);
1123 } else if (dfd == AT_FDCWD) { 1131 } else if (dfd == AT_FDCWD) {
1124 read_lock(&current->fs->lock); 1132 read_lock(&fs->lock);
1125 nd->mnt = mntget(current->fs->pwdmnt); 1133 nd->mnt = mntget(fs->pwdmnt);
1126 nd->dentry = dget(current->fs->pwd); 1134 nd->dentry = dget(fs->pwd);
1127 read_unlock(&current->fs->lock); 1135 read_unlock(&fs->lock);
1128 } else { 1136 } else {
1129 struct dentry *dentry; 1137 struct dentry *dentry;
1130 1138
@@ -1587,6 +1595,24 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
1587 return 0; 1595 return 0;
1588} 1596}
1589 1597
1598static int open_namei_create(struct nameidata *nd, struct path *path,
1599 int flag, int mode)
1600{
1601 int error;
1602 struct dentry *dir = nd->dentry;
1603
1604 if (!IS_POSIXACL(dir->d_inode))
1605 mode &= ~current->fs->umask;
1606 error = vfs_create(dir->d_inode, path->dentry, mode, nd);
1607 mutex_unlock(&dir->d_inode->i_mutex);
1608 dput(nd->dentry);
1609 nd->dentry = path->dentry;
1610 if (error)
1611 return error;
1612 /* Don't check for write permission, don't truncate */
1613 return may_open(nd, 0, flag & ~O_TRUNC);
1614}
1615
1590/* 1616/*
1591 * open_namei() 1617 * open_namei()
1592 * 1618 *
@@ -1668,18 +1694,10 @@ do_last:
1668 1694
1669 /* Negative dentry, just create the file */ 1695 /* Negative dentry, just create the file */
1670 if (!path.dentry->d_inode) { 1696 if (!path.dentry->d_inode) {
1671 if (!IS_POSIXACL(dir->d_inode)) 1697 error = open_namei_create(nd, &path, flag, mode);
1672 mode &= ~current->fs->umask;
1673 error = vfs_create(dir->d_inode, path.dentry, mode, nd);
1674 mutex_unlock(&dir->d_inode->i_mutex);
1675 dput(nd->dentry);
1676 nd->dentry = path.dentry;
1677 if (error) 1698 if (error)
1678 goto exit; 1699 goto exit;
1679 /* Don't check for write permission, don't truncate */ 1700 return 0;
1680 acc_mode = 0;
1681 flag &= ~O_TRUNC;
1682 goto ok;
1683 } 1701 }
1684 1702
1685 /* 1703 /*
@@ -1926,30 +1944,32 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
1926{ 1944{
1927 int error = 0; 1945 int error = 0;
1928 char * tmp; 1946 char * tmp;
1947 struct dentry *dentry;
1948 struct nameidata nd;
1929 1949
1930 tmp = getname(pathname); 1950 tmp = getname(pathname);
1931 error = PTR_ERR(tmp); 1951 error = PTR_ERR(tmp);
1932 if (!IS_ERR(tmp)) { 1952 if (IS_ERR(tmp))
1933 struct dentry *dentry; 1953 goto out_err;
1934 struct nameidata nd;
1935 1954
1936 error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd); 1955 error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
1937 if (error) 1956 if (error)
1938 goto out; 1957 goto out;
1939 dentry = lookup_create(&nd, 1); 1958 dentry = lookup_create(&nd, 1);
1940 error = PTR_ERR(dentry); 1959 error = PTR_ERR(dentry);
1941 if (!IS_ERR(dentry)) { 1960 if (IS_ERR(dentry))
1942 if (!IS_POSIXACL(nd.dentry->d_inode)) 1961 goto out_unlock;
1943 mode &= ~current->fs->umask;
1944 error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
1945 dput(dentry);
1946 }
1947 mutex_unlock(&nd.dentry->d_inode->i_mutex);
1948 path_release(&nd);
1949out:
1950 putname(tmp);
1951 }
1952 1962
1963 if (!IS_POSIXACL(nd.dentry->d_inode))
1964 mode &= ~current->fs->umask;
1965 error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
1966 dput(dentry);
1967out_unlock:
1968 mutex_unlock(&nd.dentry->d_inode->i_mutex);
1969 path_release(&nd);
1970out:
1971 putname(tmp);
1972out_err:
1953 return error; 1973 return error;
1954} 1974}
1955 1975
@@ -2048,10 +2068,11 @@ static long do_rmdir(int dfd, const char __user *pathname)
2048 mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT); 2068 mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
2049 dentry = lookup_hash(&nd); 2069 dentry = lookup_hash(&nd);
2050 error = PTR_ERR(dentry); 2070 error = PTR_ERR(dentry);
2051 if (!IS_ERR(dentry)) { 2071 if (IS_ERR(dentry))
2052 error = vfs_rmdir(nd.dentry->d_inode, dentry); 2072 goto exit2;
2053 dput(dentry); 2073 error = vfs_rmdir(nd.dentry->d_inode, dentry);
2054 } 2074 dput(dentry);
2075exit2:
2055 mutex_unlock(&nd.dentry->d_inode->i_mutex); 2076 mutex_unlock(&nd.dentry->d_inode->i_mutex);
2056exit1: 2077exit1:
2057 path_release(&nd); 2078 path_release(&nd);
@@ -2191,30 +2212,33 @@ asmlinkage long sys_symlinkat(const char __user *oldname,
2191 int error = 0; 2212 int error = 0;
2192 char * from; 2213 char * from;
2193 char * to; 2214 char * to;
2215 struct dentry *dentry;
2216 struct nameidata nd;
2194 2217
2195 from = getname(oldname); 2218 from = getname(oldname);
2196 if(IS_ERR(from)) 2219 if(IS_ERR(from))
2197 return PTR_ERR(from); 2220 return PTR_ERR(from);
2198 to = getname(newname); 2221 to = getname(newname);
2199 error = PTR_ERR(to); 2222 error = PTR_ERR(to);
2200 if (!IS_ERR(to)) { 2223 if (IS_ERR(to))
2201 struct dentry *dentry; 2224 goto out_putname;
2202 struct nameidata nd;
2203 2225
2204 error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd); 2226 error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
2205 if (error) 2227 if (error)
2206 goto out; 2228 goto out;
2207 dentry = lookup_create(&nd, 0); 2229 dentry = lookup_create(&nd, 0);
2208 error = PTR_ERR(dentry); 2230 error = PTR_ERR(dentry);
2209 if (!IS_ERR(dentry)) { 2231 if (IS_ERR(dentry))
2210 error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); 2232 goto out_unlock;
2211 dput(dentry); 2233
2212 } 2234 error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
2213 mutex_unlock(&nd.dentry->d_inode->i_mutex); 2235 dput(dentry);
2214 path_release(&nd); 2236out_unlock:
2237 mutex_unlock(&nd.dentry->d_inode->i_mutex);
2238 path_release(&nd);
2215out: 2239out:
2216 putname(to); 2240 putname(to);
2217 } 2241out_putname:
2218 putname(from); 2242 putname(from);
2219 return error; 2243 return error;
2220} 2244}
@@ -2300,10 +2324,11 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
2300 goto out_release; 2324 goto out_release;
2301 new_dentry = lookup_create(&nd, 0); 2325 new_dentry = lookup_create(&nd, 0);
2302 error = PTR_ERR(new_dentry); 2326 error = PTR_ERR(new_dentry);
2303 if (!IS_ERR(new_dentry)) { 2327 if (IS_ERR(new_dentry))
2304 error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); 2328 goto out_unlock;
2305 dput(new_dentry); 2329 error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
2306 } 2330 dput(new_dentry);
2331out_unlock:
2307 mutex_unlock(&nd.dentry->d_inode->i_mutex); 2332 mutex_unlock(&nd.dentry->d_inode->i_mutex);
2308out_release: 2333out_release:
2309 path_release(&nd); 2334 path_release(&nd);