Commit 32cd7468 authored by Al Viro's avatar Al Viro
Browse files

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent bdf6cbf1
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -1711,8 +1711,14 @@ static inline u64 hash_name(const char *name)
 */
static int link_path_walk(const char *name, struct nameidata *nd)
{
	struct saved {
		struct path link;
		void *cookie;
		const char *name;
	} stack[MAX_NESTED_LINKS], *last = stack + nd->depth - 1;
	int err;

start:
	while (*name=='/')
		name++;
	if (!*name)
@@ -1776,8 +1782,6 @@ Walked:
			goto Err;

		if (err) {
			struct path link;
			void *cookie;
			const char *s;

			if (unlikely(current->link_count >= MAX_NESTED_LINKS)) {
@@ -1790,22 +1794,25 @@ Walked:

			nd->depth++;
			current->link_count++;
			last++;

			link = nd->link;
			s = get_link(&link, nd, &cookie);
			last->link = nd->link;
			s = get_link(&last->link, nd, &last->cookie);

			if (unlikely(IS_ERR(s))) {
				err = PTR_ERR(s);
				current->link_count--;
				nd->depth--;
				last--;
				goto Err;
			}
			err = 0;
			if (unlikely(!s)) {
				/* jumped */
				put_link(nd, &link, cookie);
				put_link(nd, &last->link, last->cookie);
				current->link_count--;
				nd->depth--;
				last--;
			} else {
				if (*s == '/') {
					if (!nd->root.mnt)
@@ -1816,17 +1823,24 @@ Walked:
					nd->flags |= LOOKUP_JUMPED;
				}
				nd->inode = nd->path.dentry->d_inode;
				err = link_path_walk(s, nd);
				last->name = name;
				name = s;
				goto start;

back:
				name = last->name;
				if (unlikely(err)) {
					put_link(nd, &link, cookie);
					put_link(nd, &last->link, last->cookie);
					current->link_count--;
					nd->depth--;
					last--;
					goto Err;
				} else {
					err = walk_component(nd, LOOKUP_FOLLOW);
					put_link(nd, &link, cookie);
					put_link(nd, &last->link, last->cookie);
					current->link_count--;
					nd->depth--;
					last--;
					goto Walked;
				}
			}
@@ -1838,9 +1852,13 @@ Walked:
	}
	terminate_walk(nd);
Err:
	if (likely(!nd->depth))
		return err;
	goto back;
OK:
	if (likely(!nd->depth))
		return 0;
	goto back;
}

static int path_init(int dfd, const struct filename *name, unsigned int flags,