All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: viro@zeniv.linux.org.uk, brauner@kernel.org, jack@suse.cz
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable <stable@kernel.org>, Takashi Iwai <tiwai@suse.de>,
	Chuck Lever <chuck.lever@oracle.com>
Subject: [PATCH] Revert "libfs: Use d_children list to iterate simple_offset directories"
Date: Wed, 26 Feb 2025 15:29:45 +0100	[thread overview]
Message-ID: <2025022644-blinked-broadness-c810@gregkh> (raw)

This reverts commit b9b588f22a0c049a14885399e27625635ae6ef91.

There are reports of this commit breaking Chrome's rendering mode.  As
no one seems to want to do a root-cause, let's just revert it for now as
it is affecting people using the latest release as well as the stable
kernels that it has been backported to.

Link: https://lore.kernel.org/r/874j0lvy89.wl-tiwai@suse.de
Fixes: b9b588f22a0c ("libfs: Use d_children list to iterate simple_offset directories")
Cc: stable <stable@kernel.org>
Reported-by: Takashi Iwai <tiwai@suse.de>
Cc: Chuck Lever <chuck.lever@oracle.com>
Cc: Christian Brauner <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 fs/libfs.c | 90 ++++++++++++++++++------------------------------------
 1 file changed, 29 insertions(+), 61 deletions(-)

diff --git a/fs/libfs.c b/fs/libfs.c
index 8444f5cc4064..96f491f82f99 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -247,13 +247,12 @@ EXPORT_SYMBOL(simple_dir_inode_operations);
 
 /* simple_offset_add() never assigns these to a dentry */
 enum {
-	DIR_OFFSET_FIRST	= 2,		/* Find first real entry */
 	DIR_OFFSET_EOD		= S32_MAX,
 };
 
 /* simple_offset_add() allocation range */
 enum {
-	DIR_OFFSET_MIN		= DIR_OFFSET_FIRST + 1,
+	DIR_OFFSET_MIN		= 2,
 	DIR_OFFSET_MAX		= DIR_OFFSET_EOD - 1,
 };
 
@@ -458,82 +457,51 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence)
 	return vfs_setpos(file, offset, LONG_MAX);
 }
 
-static struct dentry *find_positive_dentry(struct dentry *parent,
-					   struct dentry *dentry,
-					   bool next)
+static struct dentry *offset_find_next(struct offset_ctx *octx, loff_t offset)
 {
-	struct dentry *found = NULL;
-
-	spin_lock(&parent->d_lock);
-	if (next)
-		dentry = d_next_sibling(dentry);
-	else if (!dentry)
-		dentry = d_first_child(parent);
-	hlist_for_each_entry_from(dentry, d_sib) {
-		if (!simple_positive(dentry))
-			continue;
-		spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
-		if (simple_positive(dentry))
-			found = dget_dlock(dentry);
-		spin_unlock(&dentry->d_lock);
-		if (likely(found))
-			break;
-	}
-	spin_unlock(&parent->d_lock);
-	return found;
-}
-
-static noinline_for_stack struct dentry *
-offset_dir_lookup(struct dentry *parent, loff_t offset)
-{
-	struct inode *inode = d_inode(parent);
-	struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode);
+	MA_STATE(mas, &octx->mt, offset, offset);
 	struct dentry *child, *found = NULL;
 
-	MA_STATE(mas, &octx->mt, offset, offset);
-
-	if (offset == DIR_OFFSET_FIRST)
-		found = find_positive_dentry(parent, NULL, false);
-	else {
-		rcu_read_lock();
-		child = mas_find(&mas, DIR_OFFSET_MAX);
-		found = find_positive_dentry(parent, child, false);
-		rcu_read_unlock();
-	}
+	rcu_read_lock();
+	child = mas_find(&mas, DIR_OFFSET_MAX);
+	if (!child)
+		goto out;
+	spin_lock(&child->d_lock);
+	if (simple_positive(child))
+		found = dget_dlock(child);
+	spin_unlock(&child->d_lock);
+out:
+	rcu_read_unlock();
 	return found;
 }
 
 static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry)
 {
 	struct inode *inode = d_inode(dentry);
+	long offset = dentry2offset(dentry);
 
-	return dir_emit(ctx, dentry->d_name.name, dentry->d_name.len,
-			inode->i_ino, fs_umode_to_dtype(inode->i_mode));
+	return ctx->actor(ctx, dentry->d_name.name, dentry->d_name.len, offset,
+			  inode->i_ino, fs_umode_to_dtype(inode->i_mode));
 }
 
-static void offset_iterate_dir(struct file *file, struct dir_context *ctx)
+static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
 {
-	struct dentry *dir = file->f_path.dentry;
+	struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode);
 	struct dentry *dentry;
 
-	dentry = offset_dir_lookup(dir, ctx->pos);
-	if (!dentry)
-		goto out_eod;
 	while (true) {
-		struct dentry *next;
-
-		ctx->pos = dentry2offset(dentry);
-		if (!offset_dir_emit(ctx, dentry))
-			break;
-
-		next = find_positive_dentry(dir, dentry, true);
-		dput(dentry);
-
-		if (!next)
+		dentry = offset_find_next(octx, ctx->pos);
+		if (!dentry)
 			goto out_eod;
-		dentry = next;
+
+		if (!offset_dir_emit(ctx, dentry)) {
+			dput(dentry);
+			break;
+		}
+
+		ctx->pos = dentry2offset(dentry) + 1;
+		dput(dentry);
 	}
-	dput(dentry);
 	return;
 
 out_eod:
@@ -572,7 +540,7 @@ static int offset_readdir(struct file *file, struct dir_context *ctx)
 	if (!dir_emit_dots(file, ctx))
 		return 0;
 	if (ctx->pos != DIR_OFFSET_EOD)
-		offset_iterate_dir(file, ctx);
+		offset_iterate_dir(d_inode(dir), ctx);
 	return 0;
 }
 
-- 
2.48.1


             reply	other threads:[~2025-02-26 14:31 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-26 14:29 Greg Kroah-Hartman [this message]
2025-02-26 15:57 ` [PATCH] Revert "libfs: Use d_children list to iterate simple_offset directories" Chuck Lever
2025-02-26 16:21   ` Greg Kroah-Hartman
2025-02-26 16:28     ` Chuck Lever
2025-02-26 19:13       ` Greg Kroah-Hartman
2025-02-26 20:33         ` Chuck Lever
2025-03-10 16:29           ` Greg Kroah-Hartman
2025-03-10 17:30             ` Chuck Lever
2025-03-11 13:55               ` Sun Yongjian
2025-03-11 15:23                 ` Chuck Lever
2025-03-11 18:11                   ` Darrick J. Wong
2025-03-11 18:25                     ` Chuck Lever
2025-03-11 18:52                       ` Darrick J. Wong
2025-03-11 19:39                         ` Chuck Lever
2025-03-11 21:47                           ` Kent Overstreet
2025-03-12 15:39                             ` Christoph Hellwig
2025-03-12 15:47                           ` Christoph Hellwig
2025-03-13 13:45                   ` Chuck Lever
2025-03-18 11:38                     ` Sun Yongjian

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=2025022644-blinked-broadness-c810@gregkh \
    --to=gregkh@linuxfoundation.org \
    --cc=brauner@kernel.org \
    --cc=chuck.lever@oracle.com \
    --cc=jack@suse.cz \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@kernel.org \
    --cc=tiwai@suse.de \
    --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.