Since session destroy now uses a workqueue, let l2tp_session_delete handle all the work of destroying a session. Don't remove the session from the tunnel's list immediately. The tunnel will remain extant until all of its sessions are gone anyway.
Signed-off-by: James Chapman <jchap...@katalix.com> --- net/l2tp/l2tp_core.c | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 55b1f312fedc..c909fe9273c9 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1254,36 +1254,9 @@ void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel) write_lock_bh(&tunnel->hlist_lock); for (hash = 0; hash < L2TP_HASH_SIZE; hash++) { -again: hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) { session = hlist_entry(walk, struct l2tp_session, hlist); - - l2tp_info(session, L2TP_MSG_CONTROL, - "%s: closing session\n", session->name); - - hlist_del_init(&session->hlist); - - if (test_and_set_bit(0, &session->dead)) - goto again; - - write_unlock_bh(&tunnel->hlist_lock); - - __l2tp_session_unhash(session); - l2tp_session_queue_purge(session); - - if (session->session_close != NULL) - (*session->session_close)(session); - - l2tp_session_dec_refcount(session); - - write_lock_bh(&tunnel->hlist_lock); - - /* Now restart from the beginning of this hash - * chain. We always remove a session from the - * list so we are guaranteed to make forward - * progress. - */ - goto again; + l2tp_session_delete(session); } } write_unlock_bh(&tunnel->hlist_lock); @@ -1708,6 +1681,9 @@ static void l2tp_session_del_work(struct work_struct *work) struct l2tp_session *session = container_of(work, struct l2tp_session, del_work); + l2tp_info(session, L2TP_MSG_CONTROL, + "%s: closing session\n", session->name); + __l2tp_session_unhash(session); l2tp_session_queue_purge(session); if (session->session_close) -- 1.9.1