aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2010-01-13 15:01:15 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2010-01-14 09:05:26 -0500
commit9850c056559f3633a32d810aaf00ced39437b364 (patch)
tree30e80de94e12ae758736cfb586db39cfa77d69df /fs/namei.c
parent806892e9e12e731a0ca76c8f62ad95cf8eea9614 (diff)
Fix the -ESTALE handling in do_filp_open()
Instead of playing sick games with path saving, cleanups, just retry the entire thing once with LOOKUP_REVAL added. Post-.34 we'll convert all -ESTALE handling in there to that style, rather than playing with many retry loops deep in the call chain. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/fs/namei.c b/fs/namei.c
index d930f1856ed2..94a5e60779f9 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1604,11 +1604,12 @@ struct file *do_filp_open(int dfd, const char *pathname,
1604 struct file *filp; 1604 struct file *filp;
1605 struct nameidata nd; 1605 struct nameidata nd;
1606 int error; 1606 int error;
1607 struct path path, save; 1607 struct path path;
1608 struct dentry *dir; 1608 struct dentry *dir;
1609 int count = 0; 1609 int count = 0;
1610 int will_truncate; 1610 int will_truncate;
1611 int flag = open_to_namei_flags(open_flag); 1611 int flag = open_to_namei_flags(open_flag);
1612 int force_reval = 0;
1612 1613
1613 /* 1614 /*
1614 * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only 1615 * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
@@ -1660,9 +1661,12 @@ struct file *do_filp_open(int dfd, const char *pathname,
1660 /* 1661 /*
1661 * Create - we need to know the parent. 1662 * Create - we need to know the parent.
1662 */ 1663 */
1664reval:
1663 error = path_init(dfd, pathname, LOOKUP_PARENT, &nd); 1665 error = path_init(dfd, pathname, LOOKUP_PARENT, &nd);
1664 if (error) 1666 if (error)
1665 return ERR_PTR(error); 1667 return ERR_PTR(error);
1668 if (force_reval)
1669 nd.flags |= LOOKUP_REVAL;
1666 error = path_walk(pathname, &nd); 1670 error = path_walk(pathname, &nd);
1667 if (error) { 1671 if (error) {
1668 if (nd.root.mnt) 1672 if (nd.root.mnt)
@@ -1854,17 +1858,7 @@ do_link:
1854 error = security_inode_follow_link(path.dentry, &nd); 1858 error = security_inode_follow_link(path.dentry, &nd);
1855 if (error) 1859 if (error)
1856 goto exit_dput; 1860 goto exit_dput;
1857 save = nd.path;
1858 path_get(&save);
1859 error = __do_follow_link(&path, &nd); 1861 error = __do_follow_link(&path, &nd);
1860 if (error == -ESTALE) {
1861 /* nd.path had been dropped */
1862 nd.path = save;
1863 path_get(&nd.path);
1864 nd.flags |= LOOKUP_REVAL;
1865 error = __do_follow_link(&path, &nd);
1866 }
1867 path_put(&save);
1868 path_put(&path); 1862 path_put(&path);
1869 if (error) { 1863 if (error) {
1870 /* Does someone understand code flow here? Or it is only 1864 /* Does someone understand code flow here? Or it is only
@@ -1874,6 +1868,10 @@ do_link:
1874 release_open_intent(&nd); 1868 release_open_intent(&nd);
1875 if (nd.root.mnt) 1869 if (nd.root.mnt)
1876 path_put(&nd.root); 1870 path_put(&nd.root);
1871 if (error == -ESTALE && !force_reval) {
1872 force_reval = 1;
1873 goto reval;
1874 }
1877 return ERR_PTR(error); 1875 return ERR_PTR(error);
1878 } 1876 }
1879 nd.flags &= ~LOOKUP_PARENT; 1877 nd.flags &= ~LOOKUP_PARENT;