--- x/net/can/j1939/transport.c +++ y/net/can/j1939/transport.c @@ -1083,7 +1083,6 @@ static bool j1939_session_deactivate_loc list_del_init(&session->active_session_list_entry); session->state = J1939_SESSION_DONE; - j1939_session_put(session); } return active; @@ -1098,6 +1097,9 @@ static bool j1939_session_deactivate(str active = j1939_session_deactivate_locked(session); j1939_session_list_unlock(priv); + if (active) + j1939_session_put(session); + return active; } @@ -2178,6 +2180,7 @@ void j1939_simple_recv(struct j1939_priv int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk) { struct j1939_session *session, *saved; + LIST_HEAD(active); netdev_dbg(priv->ndev, "%s, sk: %p\n", __func__, sk); j1939_session_list_lock(priv); @@ -2191,10 +2194,16 @@ int j1939_cancel_active_session(struct j j1939_session_put(session); session->err = ESHUTDOWN; - j1939_session_deactivate_locked(session); + if (j1939_session_deactivate_locked(session)) + list_move(&session->active_session_list_entry, &active); } } j1939_session_list_unlock(priv); + + list_for_each_entry_safe(session, saved, &active, active_session_list_entry) { + list_del_init(&session->active_session_list_entry); + j1939_session_put(session); + } return NOTIFY_DONE; }