aboutsummaryrefslogtreecommitdiffstats
path: root/net/l2tp
diff options
context:
space:
mode:
authorTom Parkin <tparkin@katalix.com>2013-01-31 18:43:00 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-05 14:20:30 -0500
commitf8ccac0e44934ff9414b31cc3167a5c828afec73 (patch)
treeec40a75d99912502d4bbb3df76f26d8aea96f236 /net/l2tp
parent188d1f76d0dd3715ceeadfa31376867c3395eb41 (diff)
l2tp: put tunnel socket release on a workqueue
To allow l2tp_tunnel_delete to be called from an atomic context, place the tunnel socket release calls on a workqueue for asynchronous execution. Tunnel memory is eventually freed in the tunnel socket destructor. 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')
-rw-r--r--net/l2tp/l2tp_core.c103
-rw-r--r--net/l2tp/l2tp_core.h2
2 files changed, 61 insertions, 44 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 06389d5ff120..73988c070561 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -101,6 +101,7 @@ struct l2tp_skb_cb {
101 101
102static atomic_t l2tp_tunnel_count; 102static atomic_t l2tp_tunnel_count;
103static atomic_t l2tp_session_count; 103static atomic_t l2tp_session_count;
104static struct workqueue_struct *l2tp_wq;
104 105
105/* per-net private data for this module */ 106/* per-net private data for this module */
106static unsigned int l2tp_net_id; 107static unsigned int l2tp_net_id;
@@ -122,7 +123,6 @@ static inline struct l2tp_net *l2tp_pernet(struct net *net)
122 return net_generic(net, l2tp_net_id); 123 return net_generic(net, l2tp_net_id);
123} 124}
124 125
125
126/* Tunnel reference counts. Incremented per session that is added to 126/* Tunnel reference counts. Incremented per session that is added to
127 * the tunnel. 127 * the tunnel.
128 */ 128 */
@@ -1277,6 +1277,7 @@ EXPORT_SYMBOL_GPL(l2tp_xmit_skb);
1277static void l2tp_tunnel_destruct(struct sock *sk) 1277static void l2tp_tunnel_destruct(struct sock *sk)
1278{ 1278{
1279 struct l2tp_tunnel *tunnel; 1279 struct l2tp_tunnel *tunnel;
1280 struct l2tp_net *pn;
1280 1281
1281 tunnel = sk->sk_user_data; 1282 tunnel = sk->sk_user_data;
1282 if (tunnel == NULL) 1283 if (tunnel == NULL)
@@ -1284,9 +1285,8 @@ static void l2tp_tunnel_destruct(struct sock *sk)
1284 1285
1285 l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: closing...\n", tunnel->name); 1286 l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: closing...\n", tunnel->name);
1286 1287
1287 /* Close all sessions */
1288 l2tp_tunnel_closeall(tunnel);
1289 1288
1289 /* Disable udp encapsulation */
1290 switch (tunnel->encap) { 1290 switch (tunnel->encap) {
1291 case L2TP_ENCAPTYPE_UDP: 1291 case L2TP_ENCAPTYPE_UDP:
1292 /* No longer an encapsulation socket. See net/ipv4/udp.c */ 1292 /* No longer an encapsulation socket. See net/ipv4/udp.c */
@@ -1298,17 +1298,23 @@ static void l2tp_tunnel_destruct(struct sock *sk)
1298 } 1298 }
1299 1299
1300 /* Remove hooks into tunnel socket */ 1300 /* Remove hooks into tunnel socket */
1301 tunnel->sock = NULL;
1302 sk->sk_destruct = tunnel->old_sk_destruct; 1301 sk->sk_destruct = tunnel->old_sk_destruct;
1303 sk->sk_user_data = NULL; 1302 sk->sk_user_data = NULL;
1303 tunnel->sock = NULL;
1304 1304
1305 /* Call the original destructor */ 1305 /* Remove the tunnel struct from the tunnel list */
1306 if (sk->sk_destruct) 1306 pn = l2tp_pernet(tunnel->l2tp_net);
1307 (*sk->sk_destruct)(sk); 1307 spin_lock_bh(&pn->l2tp_tunnel_list_lock);
1308 list_del_rcu(&tunnel->list);
1309 spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
1310 atomic_dec(&l2tp_tunnel_count);
1308 1311
1309 /* We're finished with the socket */ 1312 l2tp_tunnel_closeall(tunnel);
1310 l2tp_tunnel_dec_refcount(tunnel); 1313 l2tp_tunnel_dec_refcount(tunnel);
1311 1314
1315 /* Call the original destructor */
1316 if (sk->sk_destruct)
1317 (*sk->sk_destruct)(sk);
1312end: 1318end:
1313 return; 1319 return;
1314} 1320}
@@ -1382,20 +1388,41 @@ again:
1382 */ 1388 */
1383static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) 1389static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
1384{ 1390{
1385 struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
1386
1387 BUG_ON(atomic_read(&tunnel->ref_count) != 0); 1391 BUG_ON(atomic_read(&tunnel->ref_count) != 0);
1388 BUG_ON(tunnel->sock != NULL); 1392 BUG_ON(tunnel->sock != NULL);
1389
1390 l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: free...\n", tunnel->name); 1393 l2tp_info(tunnel, L2TP_MSG_CONTROL, "%s: free...\n", tunnel->name);
1391
1392 /* Remove from tunnel list */
1393 spin_lock_bh(&pn->l2tp_tunnel_list_lock);
1394 list_del_rcu(&tunnel->list);
1395 kfree_rcu(tunnel, rcu); 1394 kfree_rcu(tunnel, rcu);
1396 spin_unlock_bh(&pn->l2tp_tunnel_list_lock); 1395}
1397 1396
1398 atomic_dec(&l2tp_tunnel_count); 1397/* Workqueue tunnel deletion function */
1398static void l2tp_tunnel_del_work(struct work_struct *work)
1399{
1400 struct l2tp_tunnel *tunnel = NULL;
1401 struct socket *sock = NULL;
1402 struct sock *sk = NULL;
1403
1404 tunnel = container_of(work, struct l2tp_tunnel, del_work);
1405 sk = l2tp_tunnel_sock_lookup(tunnel);
1406 if (!sk)
1407 return;
1408
1409 sock = sk->sk_socket;
1410 BUG_ON(!sock);
1411
1412 /* Force the tunnel socket to close. This will eventually
1413 * cause the tunnel to be deleted via the normal socket close
1414 * mechanisms when userspace closes the tunnel socket.
1415 */
1416 inet_shutdown(sock, 2);
1417
1418 /* If the tunnel's socket was created by the kernel,
1419 * close the socket here since the socket was not
1420 * created by userspace.
1421 */
1422 if (sock->file == NULL)
1423 inet_release(sock);
1424
1425 l2tp_tunnel_sock_put(sk);
1399} 1426}
1400 1427
1401/* Create a socket for the tunnel, if one isn't set up by 1428/* Create a socket for the tunnel, if one isn't set up by
@@ -1657,6 +1684,9 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
1657 1684
1658 sk->sk_allocation = GFP_ATOMIC; 1685 sk->sk_allocation = GFP_ATOMIC;
1659 1686
1687 /* Init delete workqueue struct */
1688 INIT_WORK(&tunnel->del_work, l2tp_tunnel_del_work);
1689
1660 /* Add tunnel to our list */ 1690 /* Add tunnel to our list */
1661 INIT_LIST_HEAD(&tunnel->list); 1691 INIT_LIST_HEAD(&tunnel->list);
1662 atomic_inc(&l2tp_tunnel_count); 1692 atomic_inc(&l2tp_tunnel_count);
@@ -1688,33 +1718,7 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
1688 */ 1718 */
1689int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel) 1719int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
1690{ 1720{
1691 int err = -EBADF; 1721 return (false == queue_work(l2tp_wq, &tunnel->del_work));
1692 struct socket *sock = NULL;
1693 struct sock *sk = NULL;
1694
1695 sk = l2tp_tunnel_sock_lookup(tunnel);
1696 if (!sk)
1697 goto out;
1698
1699 sock = sk->sk_socket;
1700 BUG_ON(!sock);
1701
1702 /* Force the tunnel socket to close. This will eventually
1703 * cause the tunnel to be deleted via the normal socket close
1704 * mechanisms when userspace closes the tunnel socket.
1705 */
1706 err = inet_shutdown(sock, 2);
1707
1708 /* If the tunnel's socket was created by the kernel,
1709 * close the socket here since the socket was not
1710 * created by userspace.
1711 */
1712 if (sock->file == NULL)
1713 err = inet_release(sock);
1714
1715 l2tp_tunnel_sock_put(sk);
1716out:
1717 return err;
1718} 1722}
1719EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); 1723EXPORT_SYMBOL_GPL(l2tp_tunnel_delete);
1720 1724
@@ -1912,6 +1916,13 @@ static int __init l2tp_init(void)
1912 if (rc) 1916 if (rc)
1913 goto out; 1917 goto out;
1914 1918
1919 l2tp_wq = alloc_workqueue("l2tp", WQ_NON_REENTRANT | WQ_UNBOUND, 0);
1920 if (!l2tp_wq) {
1921 pr_err("alloc_workqueue failed\n");
1922 rc = -ENOMEM;
1923 goto out;
1924 }
1925
1915 pr_info("L2TP core driver, %s\n", L2TP_DRV_VERSION); 1926 pr_info("L2TP core driver, %s\n", L2TP_DRV_VERSION);
1916 1927
1917out: 1928out:
@@ -1921,6 +1932,10 @@ out:
1921static void __exit l2tp_exit(void) 1932static void __exit l2tp_exit(void)
1922{ 1933{
1923 unregister_pernet_device(&l2tp_net_ops); 1934 unregister_pernet_device(&l2tp_net_ops);
1935 if (l2tp_wq) {
1936 destroy_workqueue(l2tp_wq);
1937 l2tp_wq = NULL;
1938 }
1924} 1939}
1925 1940
1926module_init(l2tp_init); 1941module_init(l2tp_init);
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index e62204cad4fe..8eb8f1d47f3a 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -191,6 +191,8 @@ struct l2tp_tunnel {
191 int fd; /* Parent fd, if tunnel socket 191 int fd; /* Parent fd, if tunnel socket
192 * was created by userspace */ 192 * was created by userspace */
193 193
194 struct work_struct del_work;
195
194 uint8_t priv[0]; /* private data */ 196 uint8_t priv[0]; /* private data */
195}; 197};
196 198