Commit 0a959df5 authored by Al Viro's avatar Al Viro
Browse files

namei.c: separate the parts of follow_link() that find the link body



Split a piece of fs/namei.c:follow_link() that does obtaining the link
body into a separate function.  follow_link() itself is converted to
calling get_link() and then doing the body traversal (if any).

The next step will expand follow_link() call in link_path_walk()
and this helps to keep the size down...

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 680baacb
Loading
Loading
Loading
Loading
+36 −29
Original line number Diff line number Diff line
@@ -836,21 +836,22 @@ static int may_linkat(struct path *link)
	return -EPERM;
}

static __always_inline int
follow_link(struct path *link, struct nameidata *nd, void **p)
static __always_inline const char *
get_link(struct path *link, struct nameidata *nd, void **p)
{
	struct dentry *dentry = link->dentry;
	struct inode *inode = dentry->d_inode;
	int error;
	const char *s;
	const char *res;

	BUG_ON(nd->flags & LOOKUP_RCU);

	if (link->mnt == nd->path.mnt)
		mntget(link->mnt);

	error = -ELOOP;
	res = ERR_PTR(-ELOOP);
	if (unlikely(current->total_link_count >= 40))
		goto out_put_nd_path;
		goto out;

	cond_resched();
	current->total_link_count++;
@@ -858,18 +859,31 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
	touch_atime(link);

	error = security_inode_follow_link(dentry);
	res = ERR_PTR(error);
	if (error)
		goto out_put_nd_path;
		goto out;

	nd->last_type = LAST_BIND;
	*p = NULL;
	s = dentry->d_inode->i_op->follow_link(dentry, p, nd);
	error = PTR_ERR(s);
	if (IS_ERR(s))
		goto out_put_nd_path;
	res = inode->i_op->follow_link(dentry, p, nd);
	if (IS_ERR(res)) {
out:
		path_put(&nd->path);
		path_put(link);
	}
	return res;
}

	error = 0;
	if (s) {
static __always_inline int
follow_link(struct path *link, struct nameidata *nd, void **p)
{
	const char *s = get_link(link, nd, p);
	int error;

	if (unlikely(IS_ERR(s)))
		return PTR_ERR(s);
	if (unlikely(!s))
		return 0;
	if (*s == '/') {
		if (!nd->root.mnt)
			set_root(nd);
@@ -882,13 +896,6 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
	error = link_path_walk(s, nd);
	if (unlikely(error))
		put_link(nd, link, *p);
	}

	return error;

out_put_nd_path:
	path_put(&nd->path);
	path_put(link);
	return error;
}