aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-04-18 20:30:49 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-05-10 22:19:58 -0400
commit32cd74685c75fada80c9444cde150434702aba56 (patch)
treea424abaed784474a336343b45c25cc57f5d52a21 /fs/namei.c
parentbdf6cbf17923c08dafca70f0231817de1f9d1f30 (diff)
link_path_walk: kill the recursion
absolutely straightforward now - the only variables we need to preserve across the recursive call are name, link and cookie, and recursion depth is limited (and can is equal to nd->depth). So arrange an array of triples to hold instances of those and be done with that. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/fs/namei.c b/fs/namei.c
index b469ce26ff74..9844bb2f041f 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1711,8 +1711,14 @@ static inline u64 hash_name(const char *name)
1711 */ 1711 */
1712static int link_path_walk(const char *name, struct nameidata *nd) 1712static int link_path_walk(const char *name, struct nameidata *nd)
1713{ 1713{
1714 struct saved {
1715 struct path link;
1716 void *cookie;
1717 const char *name;
1718 } stack[MAX_NESTED_LINKS], *last = stack + nd->depth - 1;
1714 int err; 1719 int err;
1715 1720
1721start:
1716 while (*name=='/') 1722 while (*name=='/')
1717 name++; 1723 name++;
1718 if (!*name) 1724 if (!*name)
@@ -1776,8 +1782,6 @@ Walked:
1776 goto Err; 1782 goto Err;
1777 1783
1778 if (err) { 1784 if (err) {
1779 struct path link;
1780 void *cookie;
1781 const char *s; 1785 const char *s;
1782 1786
1783 if (unlikely(current->link_count >= MAX_NESTED_LINKS)) { 1787 if (unlikely(current->link_count >= MAX_NESTED_LINKS)) {
@@ -1790,22 +1794,25 @@ Walked:
1790 1794
1791 nd->depth++; 1795 nd->depth++;
1792 current->link_count++; 1796 current->link_count++;
1797 last++;
1793 1798
1794 link = nd->link; 1799 last->link = nd->link;
1795 s = get_link(&link, nd, &cookie); 1800 s = get_link(&last->link, nd, &last->cookie);
1796 1801
1797 if (unlikely(IS_ERR(s))) { 1802 if (unlikely(IS_ERR(s))) {
1798 err = PTR_ERR(s); 1803 err = PTR_ERR(s);
1799 current->link_count--; 1804 current->link_count--;
1800 nd->depth--; 1805 nd->depth--;
1806 last--;
1801 goto Err; 1807 goto Err;
1802 } 1808 }
1803 err = 0; 1809 err = 0;
1804 if (unlikely(!s)) { 1810 if (unlikely(!s)) {
1805 /* jumped */ 1811 /* jumped */
1806 put_link(nd, &link, cookie); 1812 put_link(nd, &last->link, last->cookie);
1807 current->link_count--; 1813 current->link_count--;
1808 nd->depth--; 1814 nd->depth--;
1815 last--;
1809 } else { 1816 } else {
1810 if (*s == '/') { 1817 if (*s == '/') {
1811 if (!nd->root.mnt) 1818 if (!nd->root.mnt)
@@ -1816,17 +1823,24 @@ Walked:
1816 nd->flags |= LOOKUP_JUMPED; 1823 nd->flags |= LOOKUP_JUMPED;
1817 } 1824 }
1818 nd->inode = nd->path.dentry->d_inode; 1825 nd->inode = nd->path.dentry->d_inode;
1819 err = link_path_walk(s, nd); 1826 last->name = name;
1827 name = s;
1828 goto start;
1829
1830back:
1831 name = last->name;
1820 if (unlikely(err)) { 1832 if (unlikely(err)) {
1821 put_link(nd, &link, cookie); 1833 put_link(nd, &last->link, last->cookie);
1822 current->link_count--; 1834 current->link_count--;
1823 nd->depth--; 1835 nd->depth--;
1836 last--;
1824 goto Err; 1837 goto Err;
1825 } else { 1838 } else {
1826 err = walk_component(nd, LOOKUP_FOLLOW); 1839 err = walk_component(nd, LOOKUP_FOLLOW);
1827 put_link(nd, &link, cookie); 1840 put_link(nd, &last->link, last->cookie);
1828 current->link_count--; 1841 current->link_count--;
1829 nd->depth--; 1842 nd->depth--;
1843 last--;
1830 goto Walked; 1844 goto Walked;
1831 } 1845 }
1832 } 1846 }
@@ -1838,9 +1852,13 @@ Walked:
1838 } 1852 }
1839 terminate_walk(nd); 1853 terminate_walk(nd);
1840Err: 1854Err:
1841 return err; 1855 if (likely(!nd->depth))
1856 return err;
1857 goto back;
1842OK: 1858OK:
1843 return 0; 1859 if (likely(!nd->depth))
1860 return 0;
1861 goto back;
1844} 1862}
1845 1863
1846static int path_init(int dfd, const struct filename *name, unsigned int flags, 1864static int path_init(int dfd, const struct filename *name, unsigned int flags,