[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20220714171653.12128-1-ubizjak@gmail.com>
Date: Thu, 14 Jul 2022 19:16:53 +0200
From: Uros Bizjak <ubizjak@...il.com>
To: linux-fsdevel@...r.kernel.org, linux-kernel@...r.kernel.org
Cc: Uros Bizjak <ubizjak@...il.com>,
Alexander Viro <viro@...iv.linux.org.uk>
Subject: [PATCH] buffer: Use try_cmpxchg in discard_buffer
Use try_cmpxchg instead of cmpxchg (*ptr, old, new) == old
in discard_buffer. x86 CMPXCHG instruction returns success in
ZF flag, so this change saves a compare after cmpxchg (and
related move instruction in front of cmpxchg).
Also, try_cmpxchg implicitly assigns old *ptr value to "old"
when cmpxchg fails, enabling further code simplifications.
Note that the value from *ptr should be read using READ_ONCE to
prevent the compiler from merging, refetching or reordering the read.
No functional change intended.
Signed-off-by: Uros Bizjak <ubizjak@...il.com>
Cc: Alexander Viro <viro@...iv.linux.org.uk>
---
fs/buffer.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 898c7f301b1b..23e1f0dcdbc4 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1464,19 +1464,15 @@ EXPORT_SYMBOL(set_bh_page);
static void discard_buffer(struct buffer_head * bh)
{
- unsigned long b_state, b_state_old;
+ unsigned long b_state;
lock_buffer(bh);
clear_buffer_dirty(bh);
bh->b_bdev = NULL;
- b_state = bh->b_state;
- for (;;) {
- b_state_old = cmpxchg(&bh->b_state, b_state,
- (b_state & ~BUFFER_FLAGS_DISCARD));
- if (b_state_old == b_state)
- break;
- b_state = b_state_old;
- }
+ b_state = READ_ONCE(bh->b_state);
+ do {
+ } while (!try_cmpxchg(&bh->b_state, &b_state,
+ b_state & ~BUFFER_FLAGS_DISCARD));
unlock_buffer(bh);
}
--
2.35.3
Powered by blists - more mailing lists