diff options
| author | Bernard Pidoux <bernard.f6bvp@gmail.com> | 2026-05-28 17:38:18 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-06-27 11:07:40 +0100 |
| commit | 35ed67c5f66dcfba53a184263bafc7c5bd542558 (patch) | |
| tree | b1b59abd56bd0742c07704dc81f9b4bc24e16a95 | |
| parent | 25982d734933184ef8c9a5d8c6ce782321e23324 (diff) | |
| download | linux-stable-35ed67c5f66dcfba53a184263bafc7c5bd542558.tar.gz linux-stable-35ed67c5f66dcfba53a184263bafc7c5bd542558.zip | |
rose: disconnect orphaned STATE_2 sockets when device is gone
commit d4f4cf9f09a3f5fafa8f09110a7c1b5d10f2f261 upstream.
When ax25stop brings down ROSE interfaces, sockets in ROSE_STATE_2
(awaiting CLEAR CONFIRM) whose device pointer is already NULL are not
reached by rose_kill_by_device() and wait for T3 (up to 180s) before
self-cleaning via rose_timer_expiry(). This keeps the rose module
usecount at 1, blocking rmmod for the full T3 duration.
In rose_heartbeat_expiry(), detect ROSE_STATE_2 sockets with no device,
cancel T3, release the neighbour reference, and call rose_disconnect()
+ sock_set_flag(SOCK_DESTROY). The next heartbeat tick (<=5s) then
destroys the socket via the existing ROSE_STATE_0/SOCK_DESTROY path,
allowing clean module unload within 10s instead of up to 180s.
Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | net/rose/rose_timer.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c index d997d24ab081..aa3dd4ab4a49 100644 --- a/net/rose/rose_timer.c +++ b/net/rose/rose_timer.c @@ -139,6 +139,20 @@ static void rose_heartbeat_expiry(struct timer_list *t) } break; + case ROSE_STATE_2: + /* Device gone before CLEAR CONFIRM arrived: stop waiting for T3 + * and disconnect now instead of blocking rmmod for up to 180s. */ + if (!rose->device) { + rose_stop_timer(sk); + if (rose->neighbour) { + rose_neigh_put(rose->neighbour); + rose->neighbour = NULL; + } + rose_disconnect(sk, ENETDOWN, -1, -1); + sock_set_flag(sk, SOCK_DESTROY); + } + break; + case ROSE_STATE_3: /* * Check for the state of the receive buffer. |
