@@ -104,9 +104,9 @@ static struct workqueue_struct *l2tp_wq;
104
104
/* per-net private data for this module */
105
105
static unsigned int l2tp_net_id ;
106
106
struct l2tp_net {
107
- struct list_head l2tp_tunnel_list ;
108
- /* Lock for write access to l2tp_tunnel_list */
109
- spinlock_t l2tp_tunnel_list_lock ;
107
+ /* Lock for write access to l2tp_tunnel_idr */
108
+ spinlock_t l2tp_tunnel_idr_lock ;
109
+ struct idr l2tp_tunnel_idr ;
110
110
struct hlist_head l2tp_session_hlist [L2TP_HASH_SIZE_2 ];
111
111
/* Lock for write access to l2tp_session_hlist */
112
112
spinlock_t l2tp_session_hlist_lock ;
@@ -208,13 +208,10 @@ struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, u32 tunnel_id)
208
208
struct l2tp_tunnel * tunnel ;
209
209
210
210
rcu_read_lock_bh ();
211
- list_for_each_entry_rcu (tunnel , & pn -> l2tp_tunnel_list , list ) {
212
- if (tunnel -> tunnel_id == tunnel_id &&
213
- refcount_inc_not_zero (& tunnel -> ref_count )) {
214
- rcu_read_unlock_bh ();
215
-
216
- return tunnel ;
217
- }
211
+ tunnel = idr_find (& pn -> l2tp_tunnel_idr , tunnel_id );
212
+ if (tunnel && refcount_inc_not_zero (& tunnel -> ref_count )) {
213
+ rcu_read_unlock_bh ();
214
+ return tunnel ;
218
215
}
219
216
rcu_read_unlock_bh ();
220
217
@@ -224,13 +221,14 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_get);
224
221
225
222
struct l2tp_tunnel * l2tp_tunnel_get_nth (const struct net * net , int nth )
226
223
{
227
- const struct l2tp_net * pn = l2tp_pernet (net );
224
+ struct l2tp_net * pn = l2tp_pernet (net );
225
+ unsigned long tunnel_id , tmp ;
228
226
struct l2tp_tunnel * tunnel ;
229
227
int count = 0 ;
230
228
231
229
rcu_read_lock_bh ();
232
- list_for_each_entry_rcu ( tunnel , & pn -> l2tp_tunnel_list , list ) {
233
- if (++ count > nth &&
230
+ idr_for_each_entry_ul ( & pn -> l2tp_tunnel_idr , tunnel , tmp , tunnel_id ) {
231
+ if (tunnel && ++ count > nth &&
234
232
refcount_inc_not_zero (& tunnel -> ref_count )) {
235
233
rcu_read_unlock_bh ();
236
234
return tunnel ;
@@ -1043,7 +1041,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns
1043
1041
IPCB (skb )-> flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED );
1044
1042
nf_reset_ct (skb );
1045
1043
1046
- bh_lock_sock (sk );
1044
+ bh_lock_sock_nested (sk );
1047
1045
if (sock_owned_by_user (sk )) {
1048
1046
kfree_skb (skb );
1049
1047
ret = NET_XMIT_DROP ;
@@ -1227,14 +1225,22 @@ static void l2tp_udp_encap_destroy(struct sock *sk)
1227
1225
l2tp_tunnel_delete (tunnel );
1228
1226
}
1229
1227
1228
+ static void l2tp_tunnel_remove (struct net * net , struct l2tp_tunnel * tunnel )
1229
+ {
1230
+ struct l2tp_net * pn = l2tp_pernet (net );
1231
+
1232
+ spin_lock_bh (& pn -> l2tp_tunnel_idr_lock );
1233
+ idr_remove (& pn -> l2tp_tunnel_idr , tunnel -> tunnel_id );
1234
+ spin_unlock_bh (& pn -> l2tp_tunnel_idr_lock );
1235
+ }
1236
+
1230
1237
/* Workqueue tunnel deletion function */
1231
1238
static void l2tp_tunnel_del_work (struct work_struct * work )
1232
1239
{
1233
1240
struct l2tp_tunnel * tunnel = container_of (work , struct l2tp_tunnel ,
1234
1241
del_work );
1235
1242
struct sock * sk = tunnel -> sock ;
1236
1243
struct socket * sock = sk -> sk_socket ;
1237
- struct l2tp_net * pn ;
1238
1244
1239
1245
l2tp_tunnel_closeall (tunnel );
1240
1246
@@ -1248,12 +1254,7 @@ static void l2tp_tunnel_del_work(struct work_struct *work)
1248
1254
}
1249
1255
}
1250
1256
1251
- /* Remove the tunnel struct from the tunnel list */
1252
- pn = l2tp_pernet (tunnel -> l2tp_net );
1253
- spin_lock_bh (& pn -> l2tp_tunnel_list_lock );
1254
- list_del_rcu (& tunnel -> list );
1255
- spin_unlock_bh (& pn -> l2tp_tunnel_list_lock );
1256
-
1257
+ l2tp_tunnel_remove (tunnel -> l2tp_net , tunnel );
1257
1258
/* drop initial ref */
1258
1259
l2tp_tunnel_dec_refcount (tunnel );
1259
1260
@@ -1384,8 +1385,6 @@ static int l2tp_tunnel_sock_create(struct net *net,
1384
1385
return err ;
1385
1386
}
1386
1387
1387
- static struct lock_class_key l2tp_socket_class ;
1388
-
1389
1388
int l2tp_tunnel_create (int fd , int version , u32 tunnel_id , u32 peer_tunnel_id ,
1390
1389
struct l2tp_tunnel_cfg * cfg , struct l2tp_tunnel * * tunnelp )
1391
1390
{
@@ -1455,12 +1454,19 @@ static int l2tp_validate_socket(const struct sock *sk, const struct net *net,
1455
1454
int l2tp_tunnel_register (struct l2tp_tunnel * tunnel , struct net * net ,
1456
1455
struct l2tp_tunnel_cfg * cfg )
1457
1456
{
1458
- struct l2tp_tunnel * tunnel_walk ;
1459
- struct l2tp_net * pn ;
1457
+ struct l2tp_net * pn = l2tp_pernet ( net ) ;
1458
+ u32 tunnel_id = tunnel -> tunnel_id ;
1460
1459
struct socket * sock ;
1461
1460
struct sock * sk ;
1462
1461
int ret ;
1463
1462
1463
+ spin_lock_bh (& pn -> l2tp_tunnel_idr_lock );
1464
+ ret = idr_alloc_u32 (& pn -> l2tp_tunnel_idr , NULL , & tunnel_id , tunnel_id ,
1465
+ GFP_ATOMIC );
1466
+ spin_unlock_bh (& pn -> l2tp_tunnel_idr_lock );
1467
+ if (ret )
1468
+ return ret == - ENOSPC ? - EEXIST : ret ;
1469
+
1464
1470
if (tunnel -> fd < 0 ) {
1465
1471
ret = l2tp_tunnel_sock_create (net , tunnel -> tunnel_id ,
1466
1472
tunnel -> peer_tunnel_id , cfg ,
@@ -1474,31 +1480,16 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
1474
1480
}
1475
1481
1476
1482
sk = sock -> sk ;
1483
+ lock_sock (sk );
1477
1484
write_lock_bh (& sk -> sk_callback_lock );
1478
1485
ret = l2tp_validate_socket (sk , net , tunnel -> encap );
1479
- if (ret < 0 )
1486
+ if (ret < 0 ) {
1487
+ release_sock (sk );
1480
1488
goto err_inval_sock ;
1489
+ }
1481
1490
rcu_assign_sk_user_data (sk , tunnel );
1482
1491
write_unlock_bh (& sk -> sk_callback_lock );
1483
1492
1484
- tunnel -> l2tp_net = net ;
1485
- pn = l2tp_pernet (net );
1486
-
1487
- sock_hold (sk );
1488
- tunnel -> sock = sk ;
1489
-
1490
- spin_lock_bh (& pn -> l2tp_tunnel_list_lock );
1491
- list_for_each_entry (tunnel_walk , & pn -> l2tp_tunnel_list , list ) {
1492
- if (tunnel_walk -> tunnel_id == tunnel -> tunnel_id ) {
1493
- spin_unlock_bh (& pn -> l2tp_tunnel_list_lock );
1494
- sock_put (sk );
1495
- ret = - EEXIST ;
1496
- goto err_sock ;
1497
- }
1498
- }
1499
- list_add_rcu (& tunnel -> list , & pn -> l2tp_tunnel_list );
1500
- spin_unlock_bh (& pn -> l2tp_tunnel_list_lock );
1501
-
1502
1493
if (tunnel -> encap == L2TP_ENCAPTYPE_UDP ) {
1503
1494
struct udp_tunnel_sock_cfg udp_cfg = {
1504
1495
.sk_user_data = tunnel ,
@@ -1512,9 +1503,16 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
1512
1503
1513
1504
tunnel -> old_sk_destruct = sk -> sk_destruct ;
1514
1505
sk -> sk_destruct = & l2tp_tunnel_destruct ;
1515
- lockdep_set_class_and_name (& sk -> sk_lock .slock , & l2tp_socket_class ,
1516
- "l2tp_sock" );
1517
1506
sk -> sk_allocation = GFP_ATOMIC ;
1507
+ release_sock (sk );
1508
+
1509
+ sock_hold (sk );
1510
+ tunnel -> sock = sk ;
1511
+ tunnel -> l2tp_net = net ;
1512
+
1513
+ spin_lock_bh (& pn -> l2tp_tunnel_idr_lock );
1514
+ idr_replace (& pn -> l2tp_tunnel_idr , tunnel , tunnel -> tunnel_id );
1515
+ spin_unlock_bh (& pn -> l2tp_tunnel_idr_lock );
1518
1516
1519
1517
trace_register_tunnel (tunnel );
1520
1518
@@ -1523,9 +1521,6 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
1523
1521
1524
1522
return 0 ;
1525
1523
1526
- err_sock :
1527
- write_lock_bh (& sk -> sk_callback_lock );
1528
- rcu_assign_sk_user_data (sk , NULL );
1529
1524
err_inval_sock :
1530
1525
write_unlock_bh (& sk -> sk_callback_lock );
1531
1526
@@ -1534,6 +1529,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
1534
1529
else
1535
1530
sockfd_put (sock );
1536
1531
err :
1532
+ l2tp_tunnel_remove (net , tunnel );
1537
1533
return ret ;
1538
1534
}
1539
1535
EXPORT_SYMBOL_GPL (l2tp_tunnel_register );
@@ -1647,8 +1643,8 @@ static __net_init int l2tp_init_net(struct net *net)
1647
1643
struct l2tp_net * pn = net_generic (net , l2tp_net_id );
1648
1644
int hash ;
1649
1645
1650
- INIT_LIST_HEAD (& pn -> l2tp_tunnel_list );
1651
- spin_lock_init (& pn -> l2tp_tunnel_list_lock );
1646
+ idr_init (& pn -> l2tp_tunnel_idr );
1647
+ spin_lock_init (& pn -> l2tp_tunnel_idr_lock );
1652
1648
1653
1649
for (hash = 0 ; hash < L2TP_HASH_SIZE_2 ; hash ++ )
1654
1650
INIT_HLIST_HEAD (& pn -> l2tp_session_hlist [hash ]);
@@ -1662,11 +1658,13 @@ static __net_exit void l2tp_exit_net(struct net *net)
1662
1658
{
1663
1659
struct l2tp_net * pn = l2tp_pernet (net );
1664
1660
struct l2tp_tunnel * tunnel = NULL ;
1661
+ unsigned long tunnel_id , tmp ;
1665
1662
int hash ;
1666
1663
1667
1664
rcu_read_lock_bh ();
1668
- list_for_each_entry_rcu (tunnel , & pn -> l2tp_tunnel_list , list ) {
1669
- l2tp_tunnel_delete (tunnel );
1665
+ idr_for_each_entry_ul (& pn -> l2tp_tunnel_idr , tunnel , tmp , tunnel_id ) {
1666
+ if (tunnel )
1667
+ l2tp_tunnel_delete (tunnel );
1670
1668
}
1671
1669
rcu_read_unlock_bh ();
1672
1670
@@ -1676,6 +1674,7 @@ static __net_exit void l2tp_exit_net(struct net *net)
1676
1674
1677
1675
for (hash = 0 ; hash < L2TP_HASH_SIZE_2 ; hash ++ )
1678
1676
WARN_ON_ONCE (!hlist_empty (& pn -> l2tp_session_hlist [hash ]));
1677
+ idr_destroy (& pn -> l2tp_tunnel_idr );
1679
1678
}
1680
1679
1681
1680
static struct pernet_operations l2tp_net_ops = {
0 commit comments