From: Joseph Qi <joseph.qi@linux.alibaba.com>
To: Andrew Morton <akpm@linux-foundation.org>,
Heming Zhao <heming.zhao@suse.com>
Cc: Mark Fasheh <mark@fasheh.com>, Joel Becker <jlbec@evilplan.org>,
ocfs2-devel@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: [PATCH 1/6] ocfs2: read the xattr entry hash before defragmenting the bucket
Date: Sat, 24 Oct 2026 23:10:07 +0800 [thread overview]
Message-ID: <20261024151012.1059683-2-joseph.qi@linux.alibaba.com> (raw)
In-Reply-To: <20261024151012.1059683-1-joseph.qi@linux.alibaba.com>
ocfs2_xattr_set_entry_index_block() takes the hash a bucket split has to
work with out of xs->here, but only after ocfs2_xattr_set_entry_bucket()
has tried and failed to fit the entry. That call defragments the bucket
when it runs out of room, and ocfs2_defrag_xattr_bucket() finishes by
sorting the entry array by name hash. lib/sort.c is not stable, so two
entries sharing a hash may trade slots and xs->here is left naming an
entry other than the one the search found.
The hash value itself survives the permutation -- the array is already
sorted, so a slot can only exchange with an equal-hash neighbour -- but
there is no reason to depend on that. Pick the hash up before the set,
where xs->here is unambiguously the entry the search landed on.
No functional change intended.
Signed-off-by: Joseph Qi <joseph.qi@linux.alibaba.com>
---
fs/ocfs2/xattr.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index b2bd06083a14..bb5b12924e1b 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -6100,6 +6100,22 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
trace_ocfs2_xattr_set_entry_index_block(xi->xi_name);
+ /*
+ * An existing entry keeps the hash it was stored under, and that is
+ * the hash a split has to work with. A new entry is stored under the
+ * unsigned one, which is what ocfs2_xa_add_entry() will write.
+ *
+ * Read it before the set below. Filling the bucket may defragment it,
+ * and ocfs2_defrag_xattr_bucket() re-sorts the entry array, so
+ * afterwards xs->here only denotes whichever entry the sort left in
+ * that slot.
+ */
+ if (xs->not_found)
+ name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name,
+ xi->xi_name_len);
+ else
+ name_hash = le32_to_cpu(xs->here->xe_name_hash);
+
ret = ocfs2_xattr_set_entry_bucket(inode, xi, xs, ctxt);
if (!ret)
goto out;
@@ -6115,17 +6131,7 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode,
* the maximum number of collisions we will allow for then is
* one bucket's worth, so check it here whether we need to
* add a new bucket for the insert.
- *
- * An existing entry keeps the hash it was stored under, and that is
- * the hash a split has to work with. A new entry is stored under the
- * unsigned one, which is what ocfs2_xa_add_entry() will write.
*/
- if (xs->not_found)
- name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name,
- xi->xi_name_len);
- else
- name_hash = le32_to_cpu(xs->here->xe_name_hash);
-
ret = ocfs2_check_xattr_bucket_collision(xs->bucket, name_hash);
if (ret) {
mlog_errno(ret);
--
2.39.3
next prev parent reply other threads:[~2026-10-24 15:10 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-24 15:10 [PATCH 0/6] ocfs2: fix stale xattr entry pointers and empty header reads Joseph Qi
2026-10-24 15:10 ` Joseph Qi [this message]
2026-10-24 15:10 ` [PATCH 2/6] ocfs2: find the xattr entry again after defragmenting a bucket Joseph Qi
2026-10-24 15:10 ` [PATCH 3/6] ocfs2: find the xattr entry again after converting a block to " Joseph Qi
2026-10-24 15:10 ` [PATCH 4/6] ocfs2: do not read the entry array of an empty xattr bucket Joseph Qi
2026-10-24 15:10 ` [PATCH 5/6] ocfs2: do not index before the entry array when dividing an empty bucket Joseph Qi
2026-10-24 15:10 ` [PATCH 6/6] ocfs2: do not read the entry array of an empty xattr block Joseph Qi
2026-10-24 17:37 ` [PATCH 0/6] ocfs2: fix stale xattr entry pointers and empty header reads Andrew Morton
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=20261024151012.1059683-2-joseph.qi@linux.alibaba.com \
--to=joseph.qi@linux.alibaba.com \
--cc=akpm@linux-foundation.org \
--cc=heming.zhao@suse.com \
--cc=jlbec@evilplan.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark@fasheh.com \
--cc=ocfs2-devel@lists.linux.dev \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®