diff options
author | Tom Parkin <tparkin@katalix.com> | 2013-03-19 06:11:23 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-03-20 12:10:39 -0400 |
commit | f6e16b299bacaa71c6604a784f2d088a966f8c23 (patch) | |
tree | 115d199ee9cd9fb9dbc296d3daad259cd9e0d682 /net/l2tp/l2tp_core.h | |
parent | 7b7c0719cd7afee725b920d75ec6a500b76107e6 (diff) | |
download | linux-f6e16b299bacaa71c6604a784f2d088a966f8c23.tar.gz linux-f6e16b299bacaa71c6604a784f2d088a966f8c23.tar.bz2 linux-f6e16b299bacaa71c6604a784f2d088a966f8c23.zip |
l2tp: unhash l2tp sessions on delete, not on free
If we postpone unhashing of l2tp sessions until the structure is freed, we
risk:
1. further packets arriving and getting queued while the pseudowire is being
closed down
2. the recv path hitting "scheduling while atomic" errors in the case that
recv drops the last reference to a session and calls l2tp_session_free
while in atomic context
As such, l2tp sessions should be unhashed from l2tp_core data structures early
in the teardown process prior to calling pseudowire close. For pseudowires
like l2tp_ppp which have multiple shutdown codepaths, provide an unhash hook.
Signed-off-by: Tom Parkin <tparkin@katalix.com>
Signed-off-by: James Chapman <jchapman@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/l2tp/l2tp_core.h')
-rw-r--r-- | net/l2tp/l2tp_core.h | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 519b013f8b31..485a490fd990 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -242,6 +242,7 @@ extern int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_i extern void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); extern int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); extern struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg); +extern void __l2tp_session_unhash(struct l2tp_session *session); extern int l2tp_session_delete(struct l2tp_session *session); extern void l2tp_session_free(struct l2tp_session *session); extern void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, unsigned char *ptr, unsigned char *optr, u16 hdrflags, int length, int (*payload_hook)(struct sk_buff *skb)); |