| From eac0e2f7139cb7a8d30c34df659d3236dc3e508b Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 17 Dec 2020 09:19:08 -0700 |
| Subject: fs: make unlazy_walk() error handling consistent |
| |
| From: Jens Axboe <axboe@kernel.dk> |
| |
| [ Upstream commit e36cffed20a324e116f329a94061ae30dd26fb51 ] |
| |
| 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: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/namei.c | 43 +++++++++++++++++-------------------------- |
| 1 file changed, 17 insertions(+), 26 deletions(-) |
| |
| diff --git a/fs/namei.c b/fs/namei.c |
| index 78443a85480a..dd85e12ac85a 100644 |
| --- a/fs/namei.c |
| +++ b/fs/namei.c |
| @@ -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 @@ OK: |
| } |
| 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 |
| -- |
| 2.30.1 |
| |