All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Layton <jlayton@kernel.org>
To: Alexander Viro <viro@zeniv.linux.org.uk>,
	 Christian Brauner <brauner@kernel.org>, Jan Kara <jack@suse.cz>,
	 Andrew Morton <akpm@linux-foundation.org>
Cc: Josef Bacik <josef@toxicpanda.com>,
	linux-fsdevel@vger.kernel.org,  linux-kernel@vger.kernel.org,
	Jeff Layton <jlayton@kernel.org>
Subject: [PATCH RFC 4/4] fs: try an opportunistic lookup for O_CREAT opens too
Date: Fri, 02 Aug 2024 17:45:05 -0400	[thread overview]
Message-ID: <20240802-openfast-v1-4-a1cff2a33063@kernel.org> (raw)
In-Reply-To: <20240802-openfast-v1-0-a1cff2a33063@kernel.org>

Today, when opening a file we'll typically do a fast lookup, but if
O_CREAT is set, the kernel always takes the exclusive inode lock. I'm
sure this was done with the expectation that O_CREAT being set means
that we expect to do the create, but that's often not the case. Many
programs set O_CREAT even in scenarios where the file already exists.

This patch rearranges the pathwalk-for-open code to also attempt a
fast_lookup in the O_CREAT case.  Have the code always do a fast_lookup
(unless O_EXCL is set), and return that without taking the inode_lock
when a positive dentry is found in the O_CREAT codepath.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
 fs/namei.c | 43 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 36 insertions(+), 7 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index b9bdb8e6214a..1793ed090314 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3538,7 +3538,7 @@ static const char *open_last_lookups(struct nameidata *nd,
 	struct dentry *dir = nd->path.dentry;
 	int open_flag = op->open_flag;
 	bool got_write = false;
-	struct dentry *dentry;
+	struct dentry *dentry = NULL;
 	const char *res;
 
 	nd->flags |= op->intent;
@@ -3549,28 +3549,57 @@ static const char *open_last_lookups(struct nameidata *nd,
 		return handle_dots(nd, nd->last_type);
 	}
 
-	if (!(open_flag & O_CREAT)) {
-		if (nd->last.name[nd->last.len])
+	/*
+	 * We _can_ be in RCU mode here. For everything but O_EXCL case, do a
+	 * fast lookup for the dentry first. For O_CREAT case, we are only
+	 * interested in positive dentries. If nothing suitable is found,
+	 * fall back to locked codepath.
+	 */
+	if ((open_flag & (O_CREAT | O_EXCL)) != (O_CREAT | O_EXCL)) {
+		/* Trailing slashes? */
+		if (unlikely(nd->last.name[nd->last.len]))
 			nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
-		/* we _can_ be in RCU mode here */
+
 		dentry = lookup_fast(nd);
 		if (IS_ERR(dentry))
 			return ERR_CAST(dentry);
+	}
+
+	if (!(open_flag & O_CREAT)) {
 		if (likely(dentry))
 			goto finish_lookup;
 
 		if (WARN_ON_ONCE(nd->flags & LOOKUP_RCU))
 			return ERR_PTR(-ECHILD);
 	} else {
-		/* create side of things */
+		/* If negative dentry was found earlier,
+		 * discard it as we'll need to use the slow path anyway.
+		 */
 		if (nd->flags & LOOKUP_RCU) {
-			if (!try_to_unlazy(nd))
+			bool unlazied;
+
+			/* discard negative dentry if one was found */
+			if (dentry && !dentry->d_inode)
+				dentry = NULL;
+
+			unlazied = dentry ? try_to_unlazy_next(nd, dentry) :
+					    try_to_unlazy(nd);
+			if (!unlazied)
 				return ERR_PTR(-ECHILD);
+		} else if (dentry && !dentry->d_inode) {
+			/* discard negative dentry if one was found */
+			dput(dentry);
+			dentry = NULL;
 		}
 		audit_inode(nd->name, dir, AUDIT_INODE_PARENT);
+
 		/* trailing slashes? */
-		if (unlikely(nd->last.name[nd->last.len]))
+		if (unlikely(nd->last.name[nd->last.len])) {
+			dput(dentry);
 			return ERR_PTR(-EISDIR);
+		}
+		if (dentry)
+			goto finish_lookup;
 	}
 
 	if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) {

-- 
2.45.2


  parent reply	other threads:[~2024-08-02 21:45 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-02 21:45 [PATCH RFC 0/4] fs: try an opportunistic lookup for O_CREAT opens too Jeff Layton
2024-08-02 21:45 ` [PATCH RFC 1/4] fs: remove comment about d_rcu_to_refcount Jeff Layton
2024-08-02 21:45 ` [PATCH RFC 2/4] fs: add a kerneldoc header over lookup_fast Jeff Layton
2024-08-02 21:45 ` [PATCH RFC 3/4] lockref: rework CMPXCHG_LOOP to handle contention better Jeff Layton
2024-08-03  4:44   ` Mateusz Guzik
2024-08-03  9:09     ` Mateusz Guzik
2024-08-03 10:59       ` Jeff Layton
2024-08-03 11:21         ` Mateusz Guzik
2024-08-03 11:32           ` Jeff Layton
2024-08-05 11:44             ` Christian Brauner
2024-08-05 12:52               ` Jeff Layton
2024-08-06 11:36                 ` Christian Brauner
2024-08-03 10:55     ` Jeff Layton
2024-08-02 21:45 ` Jeff Layton [this message]
2024-08-05 10:46 ` [PATCH RFC 0/4] fs: try an opportunistic lookup for O_CREAT opens too Christian Brauner
2024-08-05 11:55   ` Jeff Layton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240802-openfast-v1-4-a1cff2a33063@kernel.org \
    --to=jlayton@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=brauner@kernel.org \
    --cc=jack@suse.cz \
    --cc=josef@toxicpanda.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.