diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-18 20:30:49 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-05-10 22:19:58 -0400 |
| commit | 32cd74685c75fada80c9444cde150434702aba56 (patch) | |
| tree | a424abaed784474a336343b45c25cc57f5d52a21 /fs/namei.c | |
| parent | bdf6cbf17923c08dafca70f0231817de1f9d1f30 (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.c | 40 |
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 | */ |
| 1712 | static int link_path_walk(const char *name, struct nameidata *nd) | 1712 | static 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 | ||
| 1721 | start: | ||
| 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 | |||
| 1830 | back: | ||
| 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); |
| 1840 | Err: | 1854 | Err: |
| 1841 | return err; | 1855 | if (likely(!nd->depth)) |
| 1856 | return err; | ||
| 1857 | goto back; | ||
| 1842 | OK: | 1858 | OK: |
| 1843 | return 0; | 1859 | if (likely(!nd->depth)) |
| 1860 | return 0; | ||
| 1861 | goto back; | ||
| 1844 | } | 1862 | } |
| 1845 | 1863 | ||
| 1846 | static int path_init(int dfd, const struct filename *name, unsigned int flags, | 1864 | static int path_init(int dfd, const struct filename *name, unsigned int flags, |
