Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp1126810ybl; Sat, 18 Jan 2020 19:26:14 -0800 (PST) X-Google-Smtp-Source: APXvYqwwmNsTmJpSHDlmYrA0VqTFrnNgItOMFWgmDswS12/JAj4v1gFAMUXJH5ERWhwKOHMB0XvY X-Received: by 2002:a05:6830:1385:: with SMTP id d5mr12020211otq.61.1579404374790; Sat, 18 Jan 2020 19:26:14 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1579404374; cv=none; d=google.com; s=arc-20160816; b=SVpjDVYFn1EdkiJpx8DewOPB4sJiakVp7PZ+rXrN+W328YDNglEiGpS9d+7IP5EGUd yEMu94kn7/JJe5qr9W0SCQsTNwIeXAWP+GK4EKUcors78WLzSITz56XiGlY2GoGYtA8Y 887OELUpF/uAxaVUdhcmpoGS5kYzBbtU/MVJOKgOZYBtdIH7GLg2GLlkYltf81vv3m0x LH65RbVpUjTg1bOUgDBbEXRb2LELtL/QBOuhbqcgAk88YRs5immPXGazNZoPCghMMv0V ogxcz0CzKxna7t2UXskAKX/tPOO77VHUflO0VsIM6APM1HgFxheWL/zvvsxvHePHQypR INAg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=wCPhtr9LWfgfwbfSyM3+LEhiwX9rXFBYL8ERnWRwYaw=; b=F3wqH9nCSZwXvDEXwdSA9aXvT3RJFXzghe9WBpNURfFBWA17AOq41fqHpt8io84cBQ 01UwkMgm7g0SRLSonG23nDBHfkuRCgsLSNzddQBHLm57jpdpaOFV95EW59aiO1TUCOLT SwSgElw571m7kRA6BFNaCPY7ZyNPLaNMzsRXZ0uRkH2DvehdtZ4v2WvpM8004dRgnUJh 4UagaSr34x/8YVg/3X1FjkHnVy2aRC2qZZdPJtxeApQUzQpNZj0/LawgRIAqUvuB4evp zPfnWSNSh5vwEMAO7eRMot46tygFTSYQ3+cXEFamS8w0GFmTHnA3g6W+oCpRaiKHVKya 8h+w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e22si17559006oiy.124.2020.01.18.19.26.02; Sat, 18 Jan 2020 19:26:14 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726796AbgASDYP (ORCPT + 99 others); Sat, 18 Jan 2020 22:24:15 -0500 Received: from zeniv.linux.org.uk ([195.92.253.2]:56920 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725497AbgASDYO (ORCPT ); Sat, 18 Jan 2020 22:24:14 -0500 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.92.3 #3 (Red Hat Linux)) id 1it1BW-00BFfE-4R; Sun, 19 Jan 2020 03:23:40 +0000 From: Al Viro To: linux-fsdevel@vger.kernel.org Cc: Linus Torvalds , linux-kernel@vger.kernel.org, Aleksa Sarai , David Howells , Eric Biederman , Christian Brauner , Al Viro Subject: [PATCH 2/9] merging pick_link() with get_link(), part 2 Date: Sun, 19 Jan 2020 03:17:31 +0000 Message-Id: <20200119031738.2681033-19-viro@ZenIV.linux.org.uk> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200119031738.2681033-1-viro@ZenIV.linux.org.uk> References: <20200119031423.GV8904@ZenIV.linux.org.uk> <20200119031738.2681033-1-viro@ZenIV.linux.org.uk> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Al Viro Fold trailing_symlink() into lookup_last() and do_last(), change the calling conventions of those two. Rules change: success, we are done => NULL instead of 0 error => ERR_PTR(-E...) instead of -E... got a symlink to follow => return the path to be followed instead of 1 The loops calling those (in path_lookupat() and path_openat()) adjusted. A subtle change of control flow here: originally a pure-jump trailing symlink ("/" or procfs one) would've passed through the upper level loop once more, with "" for path to traverse. That would've brought us back to the lookup_last/do_last entry and we would've hit LAST_BIND case (LAST_BIND left from get_link() called by trailing_symlink()) and pretty much skip to the point right after where we'd left the sucker back when we picked that trailing symlink. Now we don't bother with that extra pass through the upper level loop - if get_link() says "I've just done a pure jump, nothing else to do", we just treat that as non-symlink case. Boilerplate added on that step will go away shortly - it'll migrate into walk_component() and then to step_into(), collapsing into the change of calling conventions for those. Signed-off-by: Al Viro --- fs/namei.c | 68 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 45cedbe267ab..d93e155caded 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2332,21 +2332,26 @@ static const char *path_init(struct nameidata *nd, unsigned flags) return s; } -static const char *trailing_symlink(struct nameidata *nd) -{ - const char *s = get_link(nd); - nd->flags |= LOOKUP_PARENT; - nd->stack[0].name = NULL; - return s ? s : ""; -} - -static inline int lookup_last(struct nameidata *nd) +static inline const char *lookup_last(struct nameidata *nd) { + int err; if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len]) nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; nd->flags &= ~LOOKUP_PARENT; - return walk_component(nd, 0); + err = walk_component(nd, 0); + if (unlikely(err)) { + const char *s; + if (err < 0) + return PTR_ERR(err); + s = get_link(nd); + if (s) { + nd->flags |= LOOKUP_PARENT; + nd->stack[0].name = NULL; + return s; + } + } + return NULL; } static int handle_lookup_down(struct nameidata *nd) @@ -2369,10 +2374,9 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path s = ERR_PTR(err); } - while (!(err = link_path_walk(s, nd)) - && ((err = lookup_last(nd)) > 0)) { - s = trailing_symlink(nd); - } + while (!(err = link_path_walk(s, nd)) && + (s = lookup_last(nd)) != NULL) + ; if (!err) err = complete_walk(nd); @@ -3184,7 +3188,7 @@ static struct dentry *lookup_open(struct nameidata *nd, struct file *file, /* * Handle the last step of open() */ -static int do_last(struct nameidata *nd, +static const char *do_last(struct nameidata *nd, struct file *file, const struct open_flags *op) { struct dentry *dir = nd->path.dentry; @@ -3203,7 +3207,7 @@ static int do_last(struct nameidata *nd, if (nd->last_type != LAST_NORM) { error = handle_dots(nd, nd->last_type); if (unlikely(error)) - return error; + return ERR_PTR(error); goto finish_open; } @@ -3213,7 +3217,7 @@ static int do_last(struct nameidata *nd, /* we _can_ be in RCU mode here */ dentry = lookup_fast(nd, &inode, &seq); if (IS_ERR(dentry)) - return PTR_ERR(dentry); + return ERR_CAST(dentry); if (likely(dentry)) goto finish_lookup; @@ -3228,12 +3232,12 @@ static int do_last(struct nameidata *nd, */ error = complete_walk(nd); if (error) - return error; + return ERR_PTR(error); audit_inode(nd->name, dir, AUDIT_INODE_PARENT); /* trailing slashes? */ if (unlikely(nd->last.name[nd->last.len])) - return -EISDIR; + return ERR_PTR(-EISDIR); } if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) { @@ -3292,18 +3296,28 @@ static int do_last(struct nameidata *nd, finish_lookup: error = step_into(nd, 0, dentry, inode, seq); - if (unlikely(error)) - return error; + if (unlikely(error)) { + const char *s; + if (error < 0) + return ERR_PTR(error); + s = get_link(nd); + if (s) { + nd->flags |= LOOKUP_PARENT; + nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); + nd->stack[0].name = NULL; + return s; + } + } if (unlikely((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))) { audit_inode(nd->name, nd->path.dentry, 0); - return -EEXIST; + return ERR_PTR(-EEXIST); } finish_open: /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */ error = complete_walk(nd); if (error) - return error; + return ERR_PTR(error); audit_inode(nd->name, nd->path.dentry, 0); if (open_flag & O_CREAT) { error = -EISDIR; @@ -3345,7 +3359,7 @@ static int do_last(struct nameidata *nd, } if (got_write) mnt_drop_write(nd->path.mnt); - return error; + return ERR_PTR(error); } struct dentry *vfs_tmpfile(struct dentry *dentry, umode_t mode, int open_flag) @@ -3448,10 +3462,8 @@ static struct file *path_openat(struct nameidata *nd, } else { const char *s = path_init(nd, flags); while (!(error = link_path_walk(s, nd)) && - (error = do_last(nd, file, op)) > 0) { - nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); - s = trailing_symlink(nd); - } + (s = do_last(nd, file, op)) != NULL) + ; terminate_walk(nd); } if (likely(!error)) { -- 2.20.1