Commit 806b681cbe588bebe8fe47dd24da62f2d1c55851
1 parent
10fa8e62f2
Exists in
master
and in
20 other branches
Turn do_link spaghetty into a normal loop
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 1 changed file with 38 additions and 45 deletions Side-by-side Diff
fs/namei.c
... | ... | @@ -1844,17 +1844,38 @@ |
1844 | 1844 | if (open_flag & O_EXCL) |
1845 | 1845 | nd.flags |= LOOKUP_EXCL; |
1846 | 1846 | filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); |
1847 | - if (!filp) | |
1848 | - goto do_link; | |
1849 | - goto out; | |
1850 | - | |
1851 | -exit_dput: | |
1852 | - path_put_conditional(&path, &nd); | |
1853 | - if (!IS_ERR(nd.intent.open.file)) | |
1854 | - release_open_intent(&nd); | |
1855 | -exit_parent: | |
1856 | - path_put(&nd.path); | |
1857 | - filp = ERR_PTR(error); | |
1847 | + while (unlikely(!filp)) { /* trailing symlink */ | |
1848 | + error = -ELOOP; | |
1849 | + if ((open_flag & O_NOFOLLOW) || count++ == 32) | |
1850 | + goto exit_dput; | |
1851 | + /* | |
1852 | + * This is subtle. Instead of calling do_follow_link() we do | |
1853 | + * the thing by hands. The reason is that this way we have zero | |
1854 | + * link_count and path_walk() (called from ->follow_link) | |
1855 | + * honoring LOOKUP_PARENT. After that we have the parent and | |
1856 | + * last component, i.e. we are in the same situation as after | |
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 | + } | |
1858 | 1879 | out: |
1859 | 1880 | if (nd.root.mnt) |
1860 | 1881 | path_put(&nd.root); |
1861 | 1882 | |
... | ... | @@ -1864,41 +1885,13 @@ |
1864 | 1885 | } |
1865 | 1886 | return filp; |
1866 | 1887 | |
1867 | -do_link: | |
1868 | - error = -ELOOP; | |
1869 | - if ((open_flag & O_NOFOLLOW) || count++ == 32) | |
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 | - */ | |
1888 | +exit_dput: | |
1889 | + path_put_conditional(&path, &nd); | |
1890 | + if (!IS_ERR(nd.intent.open.file)) | |
1892 | 1891 | release_open_intent(&nd); |
1893 | - filp = ERR_PTR(error); | |
1894 | - goto out; | |
1895 | - } | |
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; | |
1892 | +exit_parent: | |
1893 | + path_put(&nd.path); | |
1894 | + filp = ERR_PTR(error); | |
1902 | 1895 | goto out; |
1903 | 1896 | } |
1904 | 1897 |