Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5fb63c1 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Al Viro
Browse files

fs: add nd_jump_link



Add a helper that abstracts out the jump to an already parsed struct path
from ->follow_link operation from procfs.  Not only does this clean up
the code by moving the two sides of this game into a single helper, but
it also prepares for making struct nameidata private to namei.c

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 408ef013
Loading
Loading
Loading
Loading
+17 −10
Original line number Original line Diff line number Diff line
@@ -586,6 +586,21 @@ static inline void path_to_nameidata(const struct path *path,
	nd->path.dentry = path->dentry;
	nd->path.dentry = path->dentry;
}
}


/*
 * Helper to directly jump to a known parsed path from ->follow_link,
 * caller must have taken a reference to path beforehand.
 */
void nd_jump_link(struct nameidata *nd, struct path *path)
{
	path_put(&nd->path);

	nd->path = *path;
	nd->inode = nd->path.dentry->d_inode;
	nd->flags |= LOOKUP_JUMPED;

	BUG_ON(nd->inode->i_op->follow_link);
}

static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
{
{
	struct inode *inode = link->dentry->d_inode;
	struct inode *inode = link->dentry->d_inode;
@@ -630,17 +645,9 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
	s = nd_get_link(nd);
	s = nd_get_link(nd);
	if (s) {
	if (s) {
		error = __vfs_follow_link(nd, s);
		error = __vfs_follow_link(nd, s);
	} else if (nd->last_type == LAST_BIND) {
		nd->flags |= LOOKUP_JUMPED;
		nd->inode = nd->path.dentry->d_inode;
		if (nd->inode->i_op->follow_link) {
			/* stepped on a _really_ weird one */
			path_put(&nd->path);
			error = -ELOOP;
		}
	}
		if (unlikely(error))
		if (unlikely(error))
			put_link(nd, link, *p);
			put_link(nd, link, *p);
	}


	return error;
	return error;


+1 −2
Original line number Original line Diff line number Diff line
@@ -1438,8 +1438,7 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
	if (error)
	if (error)
		goto out;
		goto out;


	path_put(&nd->path);
	nd_jump_link(nd, &path);
	nd->path = path;
	return NULL;
	return NULL;
out:
out:
	return ERR_PTR(error);
	return ERR_PTR(error);
+2 −0
Original line number Original line Diff line number Diff line
@@ -80,6 +80,8 @@ extern int follow_up(struct path *);
extern struct dentry *lock_rename(struct dentry *, struct dentry *);
extern struct dentry *lock_rename(struct dentry *, struct dentry *);
extern void unlock_rename(struct dentry *, struct dentry *);
extern void unlock_rename(struct dentry *, struct dentry *);


extern void nd_jump_link(struct nameidata *nd, struct path *path);

static inline void nd_set_link(struct nameidata *nd, char *path)
static inline void nd_set_link(struct nameidata *nd, char *path)
{
{
	nd->saved_names[nd->depth] = path;
	nd->saved_names[nd->depth] = path;