aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2009-12-26 07:16:40 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2010-03-05 09:01:36 -0500
commit806b681cbe588bebe8fe47dd24da62f2d1c55851 (patch)
tree030d0e479f0c3e462930d18134a15092803d1ad3 /fs
parent10fa8e62f2bc33c452516585911f151d88389e4c (diff)
Turn do_link spaghetty into a normal loop
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/namei.c83
1 files changed, 38 insertions, 45 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 675a712137f1..08da937b1ee2 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1844,17 +1844,38 @@ reval:
1844 if (open_flag & O_EXCL) 1844 if (open_flag & O_EXCL)
1845 nd.flags |= LOOKUP_EXCL; 1845 nd.flags |= LOOKUP_EXCL;
1846 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); 1846 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
1847 if (!filp) 1847 while (unlikely(!filp)) { /* trailing symlink */
1848 goto do_link; 1848 error = -ELOOP;
1849 goto out; 1849 if ((open_flag & O_NOFOLLOW) || count++ == 32)
1850 1850 goto exit_dput;
1851exit_dput: 1851 /*
1852 path_put_conditional(&path, &nd); 1852 * This is subtle. Instead of calling do_follow_link() we do
1853 if (!IS_ERR(nd.intent.open.file)) 1853 * the thing by hands. The reason is that this way we have zero
1854 release_open_intent(&nd); 1854 * link_count and path_walk() (called from ->follow_link)
1855exit_parent: 1855 * honoring LOOKUP_PARENT. After that we have the parent and
1856 path_put(&nd.path); 1856 * last component, i.e. we are in the same situation as after
1857 filp = ERR_PTR(error); 1857 * the first path_walk(). Well, almost - if the last component
1858 * is normal we get its copy stored in nd->last.name and we will
1859 * have to putname() it when we are done. Procfs-like symlinks
1860 * just set LAST_BIND.
1861 */
1862 nd.flags |= LOOKUP_PARENT;
1863 error = security_inode_follow_link(path.dentry, &nd);
1864 if (error)
1865 goto exit_dput;
1866 error = __do_follow_link(&path, &nd);
1867 path_put(&path);
1868 if (error) {
1869 /* nd.path had been dropped */
1870 release_open_intent(&nd);
1871 filp = ERR_PTR(error);
1872 goto out;
1873 }
1874 nd.flags &= ~LOOKUP_PARENT;
1875 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
1876 if (nd.last_type == LAST_NORM)
1877 __putname(nd.last.name);
1878 }
1858out: 1879out:
1859 if (nd.root.mnt) 1880 if (nd.root.mnt)
1860 path_put(&nd.root); 1881 path_put(&nd.root);
@@ -1864,41 +1885,13 @@ out:
1864 } 1885 }
1865 return filp; 1886 return filp;
1866 1887
1867do_link: 1888exit_dput:
1868 error = -ELOOP; 1889 path_put_conditional(&path, &nd);
1869 if ((open_flag & O_NOFOLLOW) || count++ == 32) 1890 if (!IS_ERR(nd.intent.open.file))
1870 goto exit_dput;
1871 /*
1872 * This is subtle. Instead of calling do_follow_link() we do the
1873 * thing by hands. The reason is that this way we have zero link_count
1874 * and path_walk() (called from ->follow_link) honoring LOOKUP_PARENT.
1875 * After that we have the parent and last component, i.e.
1876 * we are in the same situation as after the first path_walk().
1877 * Well, almost - if the last component is normal we get its copy
1878 * stored in nd->last.name and we will have to putname() it when we
1879 * are done. Procfs-like symlinks just set LAST_BIND.
1880 */
1881 nd.flags |= LOOKUP_PARENT;
1882 error = security_inode_follow_link(path.dentry, &nd);
1883 if (error)
1884 goto exit_dput;
1885 error = __do_follow_link(&path, &nd);
1886 path_put(&path);
1887 if (error) {
1888 /* Does someone understand code flow here? Or it is only
1889 * me so stupid? Anathema to whoever designed this non-sense
1890 * with "intent.open".
1891 */
1892 release_open_intent(&nd); 1891 release_open_intent(&nd);
1893 filp = ERR_PTR(error); 1892exit_parent:
1894 goto out; 1893 path_put(&nd.path);
1895 } 1894 filp = ERR_PTR(error);
1896 nd.flags &= ~LOOKUP_PARENT;
1897 filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
1898 if (nd.last_type == LAST_NORM)
1899 __putname(nd.last.name);
1900 if (!filp)
1901 goto do_link;
1902 goto out; 1895 goto out;
1903} 1896}
1904 1897