Commit e36cffed authored by Jens Axboe's avatar Jens Axboe Committed by Al Viro
Browse files

fs: make unlazy_walk() error handling consistent



Most callers check for non-zero return, and assume it's -ECHILD (which
it always will be). One caller uses the actual error return. Clean this
up and make it fully consistent, by having unlazy_walk() return a bool
instead. Rename it to try_to_unlazy() and return true on success, and
failure on error. That's easier to read.

No functional changes in this patch.

Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 26ddb45e
Loading
Loading
Loading
Loading
+17 −26
Original line number Diff line number Diff line
@@ -669,17 +669,17 @@ static bool legitimize_root(struct nameidata *nd)
 */

/**
 * unlazy_walk - try to switch to ref-walk mode.
 * try_to_unlazy - try to switch to ref-walk mode.
 * @nd: nameidata pathwalk data
 * Returns: 0 on success, -ECHILD on failure
 * Returns: true on success, false on failure
 *
 * unlazy_walk attempts to legitimize the current nd->path and nd->root
 * try_to_unlazy attempts to legitimize the current nd->path and nd->root
 * for ref-walk mode.
 * Must be called from rcu-walk context.
 * Nothing should touch nameidata between unlazy_walk() failure and
 * Nothing should touch nameidata between try_to_unlazy() failure and
 * terminate_walk().
 */
static int unlazy_walk(struct nameidata *nd)
static bool try_to_unlazy(struct nameidata *nd)
{
	struct dentry *parent = nd->path.dentry;

@@ -694,14 +694,14 @@ static int unlazy_walk(struct nameidata *nd)
		goto out;
	rcu_read_unlock();
	BUG_ON(nd->inode != parent->d_inode);
	return 0;
	return true;

out1:
	nd->path.mnt = NULL;
	nd->path.dentry = NULL;
out:
	rcu_read_unlock();
	return -ECHILD;
	return false;
}

/**
@@ -792,7 +792,7 @@ static int complete_walk(struct nameidata *nd)
		 */
		if (!(nd->flags & (LOOKUP_ROOT | LOOKUP_IS_SCOPED)))
			nd->root.mnt = NULL;
		if (unlikely(unlazy_walk(nd)))
		if (!try_to_unlazy(nd))
			return -ECHILD;
	}

@@ -1466,7 +1466,7 @@ static struct dentry *lookup_fast(struct nameidata *nd,
		unsigned seq;
		dentry = __d_lookup_rcu(parent, &nd->last, &seq);
		if (unlikely(!dentry)) {
			if (unlazy_walk(nd))
			if (!try_to_unlazy(nd))
				return ERR_PTR(-ECHILD);
			return NULL;
		}
@@ -1567,10 +1567,8 @@ static inline int may_lookup(struct nameidata *nd)
{
	if (nd->flags & LOOKUP_RCU) {
		int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
		if (err != -ECHILD)
		if (err != -ECHILD || !try_to_unlazy(nd))
			return err;
		if (unlazy_walk(nd))
			return -ECHILD;
	}
	return inode_permission(nd->inode, MAY_EXEC);
}
@@ -1592,7 +1590,7 @@ static int reserve_stack(struct nameidata *nd, struct path *link, unsigned seq)
		// unlazy even if we fail to grab the link - cleanup needs it
		bool grabbed_link = legitimize_path(nd, link, seq);

		if (unlazy_walk(nd) != 0 || !grabbed_link)
		if (!try_to_unlazy(nd) != 0 || !grabbed_link)
			return -ECHILD;

		if (nd_alloc_stack(nd))
@@ -1634,7 +1632,7 @@ static const char *pick_link(struct nameidata *nd, struct path *link,
		touch_atime(&last->link);
		cond_resched();
	} else if (atime_needs_update(&last->link, inode)) {
		if (unlikely(unlazy_walk(nd)))
		if (!try_to_unlazy(nd))
			return ERR_PTR(-ECHILD);
		touch_atime(&last->link);
	}
@@ -1651,11 +1649,8 @@ static const char *pick_link(struct nameidata *nd, struct path *link,
		get = inode->i_op->get_link;
		if (nd->flags & LOOKUP_RCU) {
			res = get(NULL, inode, &last->done);
			if (res == ERR_PTR(-ECHILD)) {
				if (unlikely(unlazy_walk(nd)))
					return ERR_PTR(-ECHILD);
			if (res == ERR_PTR(-ECHILD) && try_to_unlazy(nd))
				res = get(link->dentry, inode, &last->done);
			}
		} else {
			res = get(link->dentry, inode, &last->done);
		}
@@ -2195,7 +2190,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
		}
		if (unlikely(!d_can_lookup(nd->path.dentry))) {
			if (nd->flags & LOOKUP_RCU) {
				if (unlazy_walk(nd))
				if (!try_to_unlazy(nd))
					return -ECHILD;
			}
			return -ENOTDIR;
@@ -3129,7 +3124,6 @@ static const char *open_last_lookups(struct nameidata *nd,
	struct inode *inode;
	struct dentry *dentry;
	const char *res;
	int error;

	nd->flags |= op->intent;

@@ -3153,9 +3147,8 @@ static const char *open_last_lookups(struct nameidata *nd,
	} else {
		/* create side of things */
		if (nd->flags & LOOKUP_RCU) {
			error = unlazy_walk(nd);
			if (unlikely(error))
				return ERR_PTR(error);
			if (!try_to_unlazy(nd))
				return ERR_PTR(-ECHILD);
		}
		audit_inode(nd->name, dir, AUDIT_INODE_PARENT);
		/* trailing slashes? */
@@ -3164,9 +3157,7 @@ static const char *open_last_lookups(struct nameidata *nd,
	}

	if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) {
		error = mnt_want_write(nd->path.mnt);
		if (!error)
			got_write = true;
		got_write = !mnt_want_write(nd->path.mnt);
		/*
		 * do _not_ fail yet - we might not need that or fail with
		 * a different error; let lookup_open() decide; we'll be