21
21
#include <linux/module.h>
22
22
#include <linux/string.h>
23
23
#include <linux/list.h>
24
+ #include <linux/rculist.h>
24
25
#include <linux/uaccess.h>
25
26
26
27
#include <linux/kernel.h>
@@ -105,9 +106,9 @@ static atomic_t l2tp_session_count;
105
106
static unsigned int l2tp_net_id ;
106
107
struct l2tp_net {
107
108
struct list_head l2tp_tunnel_list ;
108
- rwlock_t l2tp_tunnel_list_lock ;
109
+ spinlock_t l2tp_tunnel_list_lock ;
109
110
struct hlist_head l2tp_session_hlist [L2TP_HASH_SIZE_2 ];
110
- rwlock_t l2tp_session_hlist_lock ;
111
+ spinlock_t l2tp_session_hlist_lock ;
111
112
};
112
113
113
114
static inline struct l2tp_net * l2tp_pernet (struct net * net )
@@ -139,14 +140,14 @@ static struct l2tp_session *l2tp_session_find_2(struct net *net, u32 session_id)
139
140
struct l2tp_session * session ;
140
141
struct hlist_node * walk ;
141
142
142
- read_lock_bh ( & pn -> l2tp_session_hlist_lock );
143
- hlist_for_each_entry (session , walk , session_list , global_hlist ) {
143
+ rcu_read_lock_bh ( );
144
+ hlist_for_each_entry_rcu (session , walk , session_list , global_hlist ) {
144
145
if (session -> session_id == session_id ) {
145
- read_unlock_bh ( & pn -> l2tp_session_hlist_lock );
146
+ rcu_read_unlock_bh ( );
146
147
return session ;
147
148
}
148
149
}
149
- read_unlock_bh ( & pn -> l2tp_session_hlist_lock );
150
+ rcu_read_unlock_bh ( );
150
151
151
152
return NULL ;
152
153
}
@@ -225,17 +226,17 @@ struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname)
225
226
struct hlist_node * walk ;
226
227
struct l2tp_session * session ;
227
228
228
- read_lock_bh ( & pn -> l2tp_session_hlist_lock );
229
+ rcu_read_lock_bh ( );
229
230
for (hash = 0 ; hash < L2TP_HASH_SIZE_2 ; hash ++ ) {
230
- hlist_for_each_entry (session , walk , & pn -> l2tp_session_hlist [hash ], global_hlist ) {
231
+ hlist_for_each_entry_rcu (session , walk , & pn -> l2tp_session_hlist [hash ], global_hlist ) {
231
232
if (!strcmp (session -> ifname , ifname )) {
232
- read_unlock_bh ( & pn -> l2tp_session_hlist_lock );
233
+ rcu_read_unlock_bh ( );
233
234
return session ;
234
235
}
235
236
}
236
237
}
237
238
238
- read_unlock_bh ( & pn -> l2tp_session_hlist_lock );
239
+ rcu_read_unlock_bh ( );
239
240
240
241
return NULL ;
241
242
}
@@ -248,14 +249,14 @@ struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id)
248
249
struct l2tp_tunnel * tunnel ;
249
250
struct l2tp_net * pn = l2tp_pernet (net );
250
251
251
- read_lock_bh ( & pn -> l2tp_tunnel_list_lock );
252
- list_for_each_entry (tunnel , & pn -> l2tp_tunnel_list , list ) {
252
+ rcu_read_lock_bh ( );
253
+ list_for_each_entry_rcu (tunnel , & pn -> l2tp_tunnel_list , list ) {
253
254
if (tunnel -> tunnel_id == tunnel_id ) {
254
- read_unlock_bh ( & pn -> l2tp_tunnel_list_lock );
255
+ rcu_read_unlock_bh ( );
255
256
return tunnel ;
256
257
}
257
258
}
258
- read_unlock_bh ( & pn -> l2tp_tunnel_list_lock );
259
+ rcu_read_unlock_bh ( );
259
260
260
261
return NULL ;
261
262
}
@@ -267,15 +268,15 @@ struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth)
267
268
struct l2tp_tunnel * tunnel ;
268
269
int count = 0 ;
269
270
270
- read_lock_bh ( & pn -> l2tp_tunnel_list_lock );
271
- list_for_each_entry (tunnel , & pn -> l2tp_tunnel_list , list ) {
271
+ rcu_read_lock_bh ( );
272
+ list_for_each_entry_rcu (tunnel , & pn -> l2tp_tunnel_list , list ) {
272
273
if (++ count > nth ) {
273
- read_unlock_bh ( & pn -> l2tp_tunnel_list_lock );
274
+ rcu_read_unlock_bh ( );
274
275
return tunnel ;
275
276
}
276
277
}
277
278
278
- read_unlock_bh ( & pn -> l2tp_tunnel_list_lock );
279
+ rcu_read_unlock_bh ( );
279
280
280
281
return NULL ;
281
282
}
@@ -1167,9 +1168,10 @@ void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel)
1167
1168
if (tunnel -> version != L2TP_HDR_VER_2 ) {
1168
1169
struct l2tp_net * pn = l2tp_pernet (tunnel -> l2tp_net );
1169
1170
1170
- write_lock_bh (& pn -> l2tp_session_hlist_lock );
1171
- hlist_del_init (& session -> global_hlist );
1172
- write_unlock_bh (& pn -> l2tp_session_hlist_lock );
1171
+ spin_lock_bh (& pn -> l2tp_session_hlist_lock );
1172
+ hlist_del_init_rcu (& session -> global_hlist );
1173
+ spin_unlock_bh (& pn -> l2tp_session_hlist_lock );
1174
+ synchronize_rcu ();
1173
1175
}
1174
1176
1175
1177
if (session -> session_close != NULL )
@@ -1206,9 +1208,10 @@ void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
1206
1208
"%s: free...\n" , tunnel -> name );
1207
1209
1208
1210
/* Remove from tunnel list */
1209
- write_lock_bh (& pn -> l2tp_tunnel_list_lock );
1210
- list_del_init (& tunnel -> list );
1211
- write_unlock_bh (& pn -> l2tp_tunnel_list_lock );
1211
+ spin_lock_bh (& pn -> l2tp_tunnel_list_lock );
1212
+ list_del_rcu (& tunnel -> list );
1213
+ spin_unlock_bh (& pn -> l2tp_tunnel_list_lock );
1214
+ synchronize_rcu ();
1212
1215
1213
1216
atomic_dec (& l2tp_tunnel_count );
1214
1217
kfree (tunnel );
@@ -1310,9 +1313,10 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
1310
1313
1311
1314
/* Add tunnel to our list */
1312
1315
INIT_LIST_HEAD (& tunnel -> list );
1313
- write_lock_bh (& pn -> l2tp_tunnel_list_lock );
1314
- list_add (& tunnel -> list , & pn -> l2tp_tunnel_list );
1315
- write_unlock_bh (& pn -> l2tp_tunnel_list_lock );
1316
+ spin_lock_bh (& pn -> l2tp_tunnel_list_lock );
1317
+ list_add_rcu (& tunnel -> list , & pn -> l2tp_tunnel_list );
1318
+ spin_unlock_bh (& pn -> l2tp_tunnel_list_lock );
1319
+ synchronize_rcu ();
1316
1320
atomic_inc (& l2tp_tunnel_count );
1317
1321
1318
1322
/* Bump the reference count. The tunnel context is deleted
@@ -1370,9 +1374,10 @@ void l2tp_session_free(struct l2tp_session *session)
1370
1374
if (tunnel -> version != L2TP_HDR_VER_2 ) {
1371
1375
struct l2tp_net * pn = l2tp_pernet (tunnel -> l2tp_net );
1372
1376
1373
- write_lock_bh (& pn -> l2tp_session_hlist_lock );
1374
- hlist_del_init (& session -> global_hlist );
1375
- write_unlock_bh (& pn -> l2tp_session_hlist_lock );
1377
+ spin_lock_bh (& pn -> l2tp_session_hlist_lock );
1378
+ hlist_del_init_rcu (& session -> global_hlist );
1379
+ spin_unlock_bh (& pn -> l2tp_session_hlist_lock );
1380
+ synchronize_rcu ();
1376
1381
}
1377
1382
1378
1383
if (session -> session_id != 0 )
@@ -1494,10 +1499,11 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn
1494
1499
if (tunnel -> version != L2TP_HDR_VER_2 ) {
1495
1500
struct l2tp_net * pn = l2tp_pernet (tunnel -> l2tp_net );
1496
1501
1497
- write_lock_bh (& pn -> l2tp_session_hlist_lock );
1498
- hlist_add_head (& session -> global_hlist ,
1499
- l2tp_session_id_hash_2 (pn , session_id ));
1500
- write_unlock_bh (& pn -> l2tp_session_hlist_lock );
1502
+ spin_lock_bh (& pn -> l2tp_session_hlist_lock );
1503
+ hlist_add_head_rcu (& session -> global_hlist ,
1504
+ l2tp_session_id_hash_2 (pn , session_id ));
1505
+ spin_unlock_bh (& pn -> l2tp_session_hlist_lock );
1506
+ synchronize_rcu ();
1501
1507
}
1502
1508
1503
1509
/* Ignore management session in session count value */
@@ -1524,12 +1530,12 @@ static __net_init int l2tp_init_net(struct net *net)
1524
1530
return - ENOMEM ;
1525
1531
1526
1532
INIT_LIST_HEAD (& pn -> l2tp_tunnel_list );
1527
- rwlock_init (& pn -> l2tp_tunnel_list_lock );
1533
+ spin_lock_init (& pn -> l2tp_tunnel_list_lock );
1528
1534
1529
1535
for (hash = 0 ; hash < L2TP_HASH_SIZE_2 ; hash ++ )
1530
1536
INIT_HLIST_HEAD (& pn -> l2tp_session_hlist [hash ]);
1531
1537
1532
- rwlock_init (& pn -> l2tp_session_hlist_lock );
1538
+ spin_lock_init (& pn -> l2tp_session_hlist_lock );
1533
1539
1534
1540
err = net_assign_generic (net , l2tp_net_id , pn );
1535
1541
if (err )
0 commit comments