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

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
...@@ -669,17 +669,17 @@ static bool legitimize_root(struct nameidata *nd) ...@@ -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 * @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. * for ref-walk mode.
* Must be called from rcu-walk context. * 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(). * terminate_walk().
*/ */
static int unlazy_walk(struct nameidata *nd) static bool try_to_unlazy(struct nameidata *nd)
{ {
struct dentry *parent = nd->path.dentry; struct dentry *parent = nd->path.dentry;
...@@ -694,14 +694,14 @@ static int unlazy_walk(struct nameidata *nd) ...@@ -694,14 +694,14 @@ static int unlazy_walk(struct nameidata *nd)
goto out; goto out;
rcu_read_unlock(); rcu_read_unlock();
BUG_ON(nd->inode != parent->d_inode); BUG_ON(nd->inode != parent->d_inode);
return 0; return true;
out1: out1:
nd->path.mnt = NULL; nd->path.mnt = NULL;
nd->path.dentry = NULL; nd->path.dentry = NULL;
out: out:
rcu_read_unlock(); rcu_read_unlock();
return -ECHILD; return false;
} }
/** /**
...@@ -792,7 +792,7 @@ static int complete_walk(struct nameidata *nd) ...@@ -792,7 +792,7 @@ static int complete_walk(struct nameidata *nd)
*/ */
if (!(nd->flags & (LOOKUP_ROOT | LOOKUP_IS_SCOPED))) if (!(nd->flags & (LOOKUP_ROOT | LOOKUP_IS_SCOPED)))
nd->root.mnt = NULL; nd->root.mnt = NULL;
if (unlikely(unlazy_walk(nd))) if (!try_to_unlazy(nd))
return -ECHILD; return -ECHILD;
} }
...@@ -1466,7 +1466,7 @@ static struct dentry *lookup_fast(struct nameidata *nd, ...@@ -1466,7 +1466,7 @@ static struct dentry *lookup_fast(struct nameidata *nd,
unsigned seq; unsigned seq;
dentry = __d_lookup_rcu(parent, &nd->last, &seq); dentry = __d_lookup_rcu(parent, &nd->last, &seq);
if (unlikely(!dentry)) { if (unlikely(!dentry)) {
if (unlazy_walk(nd)) if (!try_to_unlazy(nd))
return ERR_PTR(-ECHILD); return ERR_PTR(-ECHILD);
return NULL; return NULL;
} }
...@@ -1567,10 +1567,8 @@ static inline int may_lookup(struct nameidata *nd) ...@@ -1567,10 +1567,8 @@ static inline int may_lookup(struct nameidata *nd)
{ {
if (nd->flags & LOOKUP_RCU) { if (nd->flags & LOOKUP_RCU) {
int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK); int err = inode_permission(nd->inode, MAY_EXEC|MAY_NOT_BLOCK);
if (err != -ECHILD) if (err != -ECHILD || !try_to_unlazy(nd))
return err; return err;
if (unlazy_walk(nd))
return -ECHILD;
} }
return inode_permission(nd->inode, MAY_EXEC); return inode_permission(nd->inode, MAY_EXEC);
} }
...@@ -1592,7 +1590,7 @@ static int reserve_stack(struct nameidata *nd, struct path *link, unsigned seq) ...@@ -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 // unlazy even if we fail to grab the link - cleanup needs it
bool grabbed_link = legitimize_path(nd, link, seq); 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; return -ECHILD;
if (nd_alloc_stack(nd)) if (nd_alloc_stack(nd))
...@@ -1634,7 +1632,7 @@ static const char *pick_link(struct nameidata *nd, struct path *link, ...@@ -1634,7 +1632,7 @@ static const char *pick_link(struct nameidata *nd, struct path *link,
touch_atime(&last->link); touch_atime(&last->link);
cond_resched(); cond_resched();
} else if (atime_needs_update(&last->link, inode)) { } else if (atime_needs_update(&last->link, inode)) {
if (unlikely(unlazy_walk(nd))) if (!try_to_unlazy(nd))
return ERR_PTR(-ECHILD); return ERR_PTR(-ECHILD);
touch_atime(&last->link); touch_atime(&last->link);
} }
...@@ -1651,11 +1649,8 @@ static const char *pick_link(struct nameidata *nd, struct path *link, ...@@ -1651,11 +1649,8 @@ static const char *pick_link(struct nameidata *nd, struct path *link,
get = inode->i_op->get_link; get = inode->i_op->get_link;
if (nd->flags & LOOKUP_RCU) { if (nd->flags & LOOKUP_RCU) {
res = get(NULL, inode, &last->done); res = get(NULL, inode, &last->done);
if (res == ERR_PTR(-ECHILD)) { if (res == ERR_PTR(-ECHILD) && try_to_unlazy(nd))
if (unlikely(unlazy_walk(nd)))
return ERR_PTR(-ECHILD);
res = get(link->dentry, inode, &last->done); res = get(link->dentry, inode, &last->done);
}
} else { } else {
res = get(link->dentry, inode, &last->done); res = get(link->dentry, inode, &last->done);
} }
...@@ -2195,7 +2190,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) ...@@ -2195,7 +2190,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
} }
if (unlikely(!d_can_lookup(nd->path.dentry))) { if (unlikely(!d_can_lookup(nd->path.dentry))) {
if (nd->flags & LOOKUP_RCU) { if (nd->flags & LOOKUP_RCU) {
if (unlazy_walk(nd)) if (!try_to_unlazy(nd))
return -ECHILD; return -ECHILD;
} }
return -ENOTDIR; return -ENOTDIR;
...@@ -3129,7 +3124,6 @@ static const char *open_last_lookups(struct nameidata *nd, ...@@ -3129,7 +3124,6 @@ static const char *open_last_lookups(struct nameidata *nd,
struct inode *inode; struct inode *inode;
struct dentry *dentry; struct dentry *dentry;
const char *res; const char *res;
int error;
nd->flags |= op->intent; nd->flags |= op->intent;
...@@ -3153,9 +3147,8 @@ static const char *open_last_lookups(struct nameidata *nd, ...@@ -3153,9 +3147,8 @@ static const char *open_last_lookups(struct nameidata *nd,
} else { } else {
/* create side of things */ /* create side of things */
if (nd->flags & LOOKUP_RCU) { if (nd->flags & LOOKUP_RCU) {
error = unlazy_walk(nd); if (!try_to_unlazy(nd))
if (unlikely(error)) return ERR_PTR(-ECHILD);
return ERR_PTR(error);
} }
audit_inode(nd->name, dir, AUDIT_INODE_PARENT); audit_inode(nd->name, dir, AUDIT_INODE_PARENT);
/* trailing slashes? */ /* trailing slashes? */
...@@ -3164,9 +3157,7 @@ static const char *open_last_lookups(struct nameidata *nd, ...@@ -3164,9 +3157,7 @@ static const char *open_last_lookups(struct nameidata *nd,
} }
if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) { if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) {
error = mnt_want_write(nd->path.mnt); got_write = !mnt_want_write(nd->path.mnt);
if (!error)
got_write = true;
/* /*
* do _not_ fail yet - we might not need that or fail with * do _not_ fail yet - we might not need that or fail with
* a different error; let lookup_open() decide; we'll be * a different error; let lookup_open() decide; we'll be
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment