[PATCH net v3 2/5] net/rds: clear cp_flags bits individually in rds_conn_path_reset()
Allison Henderson <[email protected]>
| Newsgroups | org.kernel.vger.linux-rdma,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
rds_conn_path_reset() wipes the whole flag word with a plain
cp->cp_flags = 0 store. Every other accessor of that word uses
atomic bitops, and some of them can run concurrently with the reset:
RDS_LL_SEND_FULL is set from rds_send_xmit() and cleared from the
transport completion paths, neither of which holds anything that
excludes the shutdown worker. A plain store racing an atomic
read-modify-write on the same word is a data race, and whichever
side loses has its update silently discarded.
Clear the two bits the reset is actually responsible for instead.
RDS_IN_XMIT and RDS_RECV_REFILL need no store at all here: they
belong to the caller, rds_conn_shutdown(), which waits for both to be
clear before calling the transport shutdown and this reset.
This also gives every bit in cp_flags a single well-defined writer
discipline, which the following patches rely on when they turn
RDS_IN_XMIT and RDS_RECV_REFILL into bit locks held across the
teardown: a blanket store mid-teardown would destroy lock ownership
that an atomic clear preserves.
Oracle UEK carries the same conversion ("net/rds: Preserve essential
connection state flags"), motivated by its asynchronous shutdown
state machine, whose progress and destroy flags must survive the
reset. UEK's variant also clears RDS_IN_XMIT and RDS_RECV_REFILL
because there the reset runs as the final step of a teardown that
owns both bits, making those clears its unlock. Upstream that
release belongs in rds_conn_shutdown(): once a later patch in this
series turns the two bits into locks held across the teardown, ending
ownership needs release semantics and a wake-up that a plain clear
inside the reset would not provide.
Based on Oracle UEK commit "net/rds: Preserve essential connection
state flags" by Gerd Rausch.
Fixes: 00e0f34c6166 ("RDS: Connection handling")
Assisted-by: Claude-Code:claude-fable-5
Signed-off-by: Allison Henderson <[email protected]>
---
v3: reword the comment and changelog so they no longer claim a
quiescence guarantee that only patch 5 delivers; the bits are
described as belonging to rds_conn_shutdown() and left alone here
v2: add Fixes tag
net/rds/connection.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/net/rds/connection.c b/net/rds/connection.c
index 7c8ab8e973e1..46ac72088f84 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -120,7 +120,15 @@ static void rds_conn_path_reset(struct rds_conn_path *cp)
rds_stats_inc(s_conn_reset);
rds_send_path_reset(cp);
- cp->cp_flags = 0;
+
+ /* Clear the bits the reset is responsible for individually: a
+ * blanket cp_flags = 0 is a plain store that can clobber a
+ * concurrent atomic read-modify-write on the same word.
+ * RDS_IN_XMIT and RDS_RECV_REFILL belong to the caller,
+ * rds_conn_shutdown(), and are left alone here.
+ */
+ clear_bit(RDS_LL_SEND_FULL, &cp->cp_flags);
+ clear_bit(RDS_RECONNECT_PENDING, &cp->cp_flags);
/* Do not clear next_rx_seq here, else we cannot distinguish
* retransmitted packets from new packets, and will hand all
--
2.25.1