aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/namei.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/fs/namei.c b/fs/namei.c
index ac6d214da827..5008f01787f5 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -852,7 +852,7 @@ static int follow_managed(struct path *path, unsigned flags)
852 mntput(path->mnt); 852 mntput(path->mnt);
853 if (ret == -EISDIR) 853 if (ret == -EISDIR)
854 ret = 0; 854 ret = 0;
855 return ret; 855 return ret < 0 ? ret : need_mntput;
856} 856}
857 857
858int follow_down_one(struct path *path) 858int follow_down_one(struct path *path)
@@ -900,6 +900,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
900 break; 900 break;
901 path->mnt = mounted; 901 path->mnt = mounted;
902 path->dentry = mounted->mnt_root; 902 path->dentry = mounted->mnt_root;
903 nd->flags |= LOOKUP_JUMPED;
903 nd->seq = read_seqcount_begin(&path->dentry->d_seq); 904 nd->seq = read_seqcount_begin(&path->dentry->d_seq);
904 /* 905 /*
905 * Update the inode too. We don't need to re-check the 906 * Update the inode too. We don't need to re-check the
@@ -1213,6 +1214,8 @@ retry:
1213 path_put_conditional(path, nd); 1214 path_put_conditional(path, nd);
1214 return err; 1215 return err;
1215 } 1216 }
1217 if (err)
1218 nd->flags |= LOOKUP_JUMPED;
1216 *inode = path->dentry->d_inode; 1219 *inode = path->dentry->d_inode;
1217 return 0; 1220 return 0;
1218} 1221}
@@ -2146,6 +2149,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2146 } 2149 }
2147 2150
2148 /* create side of things */ 2151 /* create side of things */
2152 /*
2153 * This will *only* deal with leaving RCU mode - LOOKUP_JUMPED has been
2154 * cleared when we got to the last component we are about to look up
2155 */
2149 error = complete_walk(nd); 2156 error = complete_walk(nd);
2150 if (error) 2157 if (error)
2151 return ERR_PTR(error); 2158 return ERR_PTR(error);
@@ -2214,6 +2221,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2214 if (error < 0) 2221 if (error < 0)
2215 goto exit_dput; 2222 goto exit_dput;
2216 2223
2224 if (error)
2225 nd->flags |= LOOKUP_JUMPED;
2226
2217 error = -ENOENT; 2227 error = -ENOENT;
2218 if (!path->dentry->d_inode) 2228 if (!path->dentry->d_inode)
2219 goto exit_dput; 2229 goto exit_dput;
@@ -2223,6 +2233,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2223 2233
2224 path_to_nameidata(path, nd); 2234 path_to_nameidata(path, nd);
2225 nd->inode = path->dentry->d_inode; 2235 nd->inode = path->dentry->d_inode;
2236 /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */
2237 error = complete_walk(nd);
2238 if (error)
2239 goto exit;
2226 error = -EISDIR; 2240 error = -EISDIR;
2227 if (S_ISDIR(nd->inode->i_mode)) 2241 if (S_ISDIR(nd->inode->i_mode))
2228 goto exit; 2242 goto exit;