mirror of
https://github.com/torvalds/linux.git
synced 2026-09-11 20:13:02 +02:00
net/rds: clear cp_flags bits individually in rds_conn_path_reset()
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: 00e0f34c61 ("RDS: Connection handling")
Signed-off-by: Allison Henderson <achender@kernel.org>
Link: https://patch.msgid.link/20260828223921.202913-4-achender@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
17c4476dbb
commit
103c4b13c4
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user