[PATCH AUTOSEL 6.19-5.10] net/rds: Clear reconnect pending bit

Sasha Levin
2026-02-14T21:25:23Z

From: Håkon Bugge <haakon.bugge@oracle.com>

[ Upstream commit b89fc7c2523b2b0750d91840f4e52521270d70ed ]

When canceling the reconnect worker, care must be taken to reset the
reconnect-pending bit. If the reconnect worker has not yet been
scheduled before it is canceled, the reconnect-pending bit will stay
on forever.

Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
Link: https://patch.msgid.link/20260203055723.1085751-6-achender@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

### 3. BUG MECHANISM — CLEAR AND CRITICAL

Now the full picture is clear:

**The flow:**
1. `rds_queue_reconnect()` at line 138 sets `RDS_RECONNECT_PENDING` and
queues the delayed work.
2. `rds_connect_worker()` (the worker function) at line 173 clears
`RDS_RECONNECT_PENDING` when it runs.
3. `rds_conn_path_connect_if_down()` at line 911 uses
`test_and_set_bit(RDS_RECONNECT_PENDING, ...)` — if the bit is
already set, it returns without queuing work, trusting that a
reconnect is already pending.

**The bug:**
In `rds_conn_shutdown()`, `cancel_delayed_work_sync()` cancels the
queued worker. If the worker hadn't started yet, it never runs
`clear_bit(RDS_RECONNECT_PENDING, ...)`. The bit stays set. Then when
`rds_conn_path_connect_if_down()` is later called (e.g., when trying to
send data), `test_and_set_bit` finds the bit already set and skips
queuing — **forever**. The connection can never reconnect.

This is a **permanent connection failure** bug — once triggered, the RDS
connection path is effectively dead until the system is rebooted or the
module is reloaded.

### 4. CLASSIFICATION

- **Bug type:** State corruption / logic bug leading to permanent loss
of network connectivity
- **Severity:** HIGH — RDS is used in production Oracle RAC clusters and
RDMA-based environments
- **Trigger:** Race between shutdown and reconnect scheduling —
realistic in production with network flaps

### 5. SCOPE AND RISK

- **Change size:** 1 functional line (plus 1 blank line) — extremely
small and surgical
- **Files changed:** 1 file (`net/rds/connection.c`)
- **Risk of regression:** Very low — `clear_bit` is idempotent. If the
worker already ran and cleared the bit, clearing it again is harmless.
If the worker didn't run, this is the correct fix.
- **The fix is placed correctly:** After `cancel_delayed_work_sync()`
guarantees the worker won't run, and before `rds_queue_reconnect()`
which will set the bit again if needed.

### 6. STABLE KERNEL CRITERIA

- **Obviously correct:** Yes — the logic is straightforward and well-
explained
- **Fixes a real bug:** Yes — permanent loss of RDS connectivity
- **Important issue:** Yes — affects network reliability for RDS users
(Oracle, RDMA environments)
- **Small and contained:** Yes — 1 line in 1 file
- **No new features:** Correct — purely a bug fix
- **No new APIs:** Correct

### 7. DEPENDENCY CHECK

This fix is self-contained. It only adds a `clear_bit()` call after an
existing `cancel_delayed_work_sync()` call. The `RDS_RECONNECT_PENDING`
flag and the surrounding code have been in the kernel for a long time.
This should apply cleanly to any stable tree that has the RDS subsystem.

### Conclusion

This is a textbook stable backport candidate: a tiny, obviously correct,
one-line fix for a serious bug (permanent connection failure) in
networking code used in production environments. The fix has zero risk
of regression due to the idempotent nature of `clear_bit`, and the bug
mechanism is clearly explained and verified through code analysis.

**YES**

net/rds/connection.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/net/rds/connection.c b/net/rds/connection.c
index ad8027e6f54ef..dbfea6fa11260 100644
--- a/net/rds/connection.c
+++ b/net/rds/connection.c
@@ -429,6 +429,8 @@ void rds_conn_shutdown(struct rds_conn_path *cp)
* to the conn hash, so we never trigger a reconnect on this
* conn - the reconnect is always triggered by the active peer. */
cancel_delayed_work_sync(&cp->cp_conn_w);
+
+ clear_bit(RDS_RECONNECT_PENDING, &cp->cp_flags);
rcu_read_lock();
if (!hlist_unhashed(&conn->c_hash_node)) {
rcu_read_unlock();
--
2.51.0