@@ -100,8 +100,8 @@ struct pppoe_net {
100100 * as well, moreover in case of SMP less locking
101101 * controversy here
102102 */
103- struct pppox_sock * hash_table [PPPOE_HASH_SIZE ];
104- rwlock_t hash_lock ;
103+ struct pppox_sock __rcu * hash_table [PPPOE_HASH_SIZE ];
104+ spinlock_t hash_lock ;
105105};
106106
107107/*
@@ -162,13 +162,13 @@ static struct pppox_sock *__get_item(struct pppoe_net *pn, __be16 sid,
162162 int hash = hash_item (sid , addr );
163163 struct pppox_sock * ret ;
164164
165- ret = pn -> hash_table [hash ];
165+ ret = rcu_dereference ( pn -> hash_table [hash ]) ;
166166 while (ret ) {
167167 if (cmp_addr (& ret -> pppoe_pa , sid , addr ) &&
168168 ret -> pppoe_ifindex == ifindex )
169169 return ret ;
170170
171- ret = ret -> next ;
171+ ret = rcu_dereference ( ret -> next ) ;
172172 }
173173
174174 return NULL ;
@@ -177,19 +177,20 @@ static struct pppox_sock *__get_item(struct pppoe_net *pn, __be16 sid,
177177static int __set_item (struct pppoe_net * pn , struct pppox_sock * po )
178178{
179179 int hash = hash_item (po -> pppoe_pa .sid , po -> pppoe_pa .remote );
180- struct pppox_sock * ret ;
180+ struct pppox_sock * ret , * first ;
181181
182- ret = pn -> hash_table [hash ];
182+ first = rcu_dereference_protected (pn -> hash_table [hash ], lockdep_is_held (& pn -> hash_lock ));
183+ ret = first ;
183184 while (ret ) {
184185 if (cmp_2_addr (& ret -> pppoe_pa , & po -> pppoe_pa ) &&
185186 ret -> pppoe_ifindex == po -> pppoe_ifindex )
186187 return - EALREADY ;
187188
188- ret = ret -> next ;
189+ ret = rcu_dereference_protected ( ret -> next , lockdep_is_held ( & pn -> hash_lock )) ;
189190 }
190191
191- po -> next = pn -> hash_table [ hash ] ;
192- pn -> hash_table [hash ] = po ;
192+ RCU_INIT_POINTER ( po -> next , first ) ;
193+ rcu_assign_pointer ( pn -> hash_table [hash ], po ) ;
193194
194195 return 0 ;
195196}
@@ -198,20 +199,24 @@ static void __delete_item(struct pppoe_net *pn, __be16 sid,
198199 char * addr , int ifindex )
199200{
200201 int hash = hash_item (sid , addr );
201- struct pppox_sock * ret , * * src ;
202+ struct pppox_sock * ret , __rcu * * src ;
202203
203- ret = pn -> hash_table [hash ];
204+ ret = rcu_dereference_protected ( pn -> hash_table [hash ], lockdep_is_held ( & pn -> hash_lock )) ;
204205 src = & pn -> hash_table [hash ];
205206
206207 while (ret ) {
207208 if (cmp_addr (& ret -> pppoe_pa , sid , addr ) &&
208209 ret -> pppoe_ifindex == ifindex ) {
209- * src = ret -> next ;
210+ struct pppox_sock * next ;
211+
212+ next = rcu_dereference_protected (ret -> next ,
213+ lockdep_is_held (& pn -> hash_lock ));
214+ rcu_assign_pointer (* src , next );
210215 break ;
211216 }
212217
213218 src = & ret -> next ;
214- ret = ret -> next ;
219+ ret = rcu_dereference_protected ( ret -> next , lockdep_is_held ( & pn -> hash_lock )) ;
215220 }
216221}
217222
@@ -225,11 +230,9 @@ static inline struct pppox_sock *get_item(struct pppoe_net *pn, __be16 sid,
225230{
226231 struct pppox_sock * po ;
227232
228- read_lock_bh (& pn -> hash_lock );
229233 po = __get_item (pn , sid , addr , ifindex );
230- if (po )
231- sock_hold (sk_pppox (po ));
232- read_unlock_bh (& pn -> hash_lock );
234+ if (po && !refcount_inc_not_zero (& sk_pppox (po )-> sk_refcnt ))
235+ po = NULL ;
233236
234237 return po ;
235238}
@@ -258,9 +261,9 @@ static inline struct pppox_sock *get_item_by_addr(struct net *net,
258261static inline void delete_item (struct pppoe_net * pn , __be16 sid ,
259262 char * addr , int ifindex )
260263{
261- write_lock_bh (& pn -> hash_lock );
264+ spin_lock (& pn -> hash_lock );
262265 __delete_item (pn , sid , addr , ifindex );
263- write_unlock_bh (& pn -> hash_lock );
266+ spin_unlock (& pn -> hash_lock );
264267}
265268
266269/***************************************************************************
@@ -276,14 +279,16 @@ static void pppoe_flush_dev(struct net_device *dev)
276279 int i ;
277280
278281 pn = pppoe_pernet (dev_net (dev ));
279- write_lock_bh (& pn -> hash_lock );
282+ spin_lock (& pn -> hash_lock );
280283 for (i = 0 ; i < PPPOE_HASH_SIZE ; i ++ ) {
281- struct pppox_sock * po = pn -> hash_table [i ];
284+ struct pppox_sock * po = rcu_dereference_protected (pn -> hash_table [i ],
285+ lockdep_is_held (& pn -> hash_lock ));
282286 struct sock * sk ;
283287
284288 while (po ) {
285289 while (po && po -> pppoe_dev != dev ) {
286- po = po -> next ;
290+ po = rcu_dereference_protected (po -> next ,
291+ lockdep_is_held (& pn -> hash_lock ));
287292 }
288293
289294 if (!po )
@@ -300,7 +305,7 @@ static void pppoe_flush_dev(struct net_device *dev)
300305 */
301306
302307 sock_hold (sk );
303- write_unlock_bh (& pn -> hash_lock );
308+ spin_unlock (& pn -> hash_lock );
304309 lock_sock (sk );
305310
306311 if (po -> pppoe_dev == dev &&
@@ -320,11 +325,12 @@ static void pppoe_flush_dev(struct net_device *dev)
320325 */
321326
322327 BUG_ON (pppoe_pernet (dev_net (dev )) == NULL );
323- write_lock_bh (& pn -> hash_lock );
324- po = pn -> hash_table [i ];
328+ spin_lock (& pn -> hash_lock );
329+ po = rcu_dereference_protected (pn -> hash_table [i ],
330+ lockdep_is_held (& pn -> hash_lock ));
325331 }
326332 }
327- write_unlock_bh (& pn -> hash_lock );
333+ spin_unlock (& pn -> hash_lock );
328334}
329335
330336static int pppoe_device_event (struct notifier_block * this ,
@@ -528,6 +534,11 @@ static struct proto pppoe_sk_proto __read_mostly = {
528534 .obj_size = sizeof (struct pppox_sock ),
529535};
530536
537+ static void pppoe_destruct (struct sock * sk )
538+ {
539+ skb_queue_purge (& sk -> sk_receive_queue );
540+ }
541+
531542/***********************************************************************
532543 *
533544 * Initialize a new struct sock.
@@ -542,11 +553,13 @@ static int pppoe_create(struct net *net, struct socket *sock, int kern)
542553 return - ENOMEM ;
543554
544555 sock_init_data (sock , sk );
556+ sock_set_flag (sk , SOCK_RCU_FREE );
545557
546558 sock -> state = SS_UNCONNECTED ;
547559 sock -> ops = & pppoe_ops ;
548560
549561 sk -> sk_backlog_rcv = pppoe_rcv_core ;
562+ sk -> sk_destruct = pppoe_destruct ;
550563 sk -> sk_state = PPPOX_NONE ;
551564 sk -> sk_type = SOCK_STREAM ;
552565 sk -> sk_family = PF_PPPOX ;
@@ -599,7 +612,6 @@ static int pppoe_release(struct socket *sock)
599612 sock_orphan (sk );
600613 sock -> sk = NULL ;
601614
602- skb_queue_purge (& sk -> sk_receive_queue );
603615 release_sock (sk );
604616 sock_put (sk );
605617
@@ -681,9 +693,9 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
681693 & sp -> sa_addr .pppoe ,
682694 sizeof (struct pppoe_addr ));
683695
684- write_lock_bh (& pn -> hash_lock );
696+ spin_lock (& pn -> hash_lock );
685697 error = __set_item (pn , po );
686- write_unlock_bh (& pn -> hash_lock );
698+ spin_unlock (& pn -> hash_lock );
687699 if (error < 0 )
688700 goto err_put ;
689701
@@ -1052,11 +1064,11 @@ static inline struct pppox_sock *pppoe_get_idx(struct pppoe_net *pn, loff_t pos)
10521064 int i ;
10531065
10541066 for (i = 0 ; i < PPPOE_HASH_SIZE ; i ++ ) {
1055- po = pn -> hash_table [i ];
1067+ po = rcu_dereference ( pn -> hash_table [i ]) ;
10561068 while (po ) {
10571069 if (!pos -- )
10581070 goto out ;
1059- po = po -> next ;
1071+ po = rcu_dereference ( po -> next ) ;
10601072 }
10611073 }
10621074
@@ -1065,34 +1077,35 @@ static inline struct pppox_sock *pppoe_get_idx(struct pppoe_net *pn, loff_t pos)
10651077}
10661078
10671079static void * pppoe_seq_start (struct seq_file * seq , loff_t * pos )
1068- __acquires (pn - > hash_lock )
1080+ __acquires (RCU )
10691081{
10701082 struct pppoe_net * pn = pppoe_pernet (seq_file_net (seq ));
10711083 loff_t l = * pos ;
10721084
1073- read_lock_bh ( & pn -> hash_lock );
1085+ rcu_read_lock ( );
10741086 return l ? pppoe_get_idx (pn , -- l ) : SEQ_START_TOKEN ;
10751087}
10761088
10771089static void * pppoe_seq_next (struct seq_file * seq , void * v , loff_t * pos )
10781090{
10791091 struct pppoe_net * pn = pppoe_pernet (seq_file_net (seq ));
1080- struct pppox_sock * po ;
1092+ struct pppox_sock * po , * next ;
10811093
10821094 ++ * pos ;
10831095 if (v == SEQ_START_TOKEN ) {
10841096 po = pppoe_get_idx (pn , 0 );
10851097 goto out ;
10861098 }
10871099 po = v ;
1088- if (po -> next )
1089- po = po -> next ;
1100+ next = rcu_dereference (po -> next );
1101+ if (next )
1102+ po = next ;
10901103 else {
10911104 int hash = hash_item (po -> pppoe_pa .sid , po -> pppoe_pa .remote );
10921105
10931106 po = NULL ;
10941107 while (++ hash < PPPOE_HASH_SIZE ) {
1095- po = pn -> hash_table [hash ];
1108+ po = rcu_dereference ( pn -> hash_table [hash ]) ;
10961109 if (po )
10971110 break ;
10981111 }
@@ -1103,10 +1116,9 @@ static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos)
11031116}
11041117
11051118static void pppoe_seq_stop (struct seq_file * seq , void * v )
1106- __releases (pn - > hash_lock )
1119+ __releases (RCU )
11071120{
1108- struct pppoe_net * pn = pppoe_pernet (seq_file_net (seq ));
1109- read_unlock_bh (& pn -> hash_lock );
1121+ rcu_read_unlock ();
11101122}
11111123
11121124static const struct seq_operations pppoe_seq_ops = {
@@ -1149,7 +1161,7 @@ static __net_init int pppoe_init_net(struct net *net)
11491161 struct pppoe_net * pn = pppoe_pernet (net );
11501162 struct proc_dir_entry * pde ;
11511163
1152- rwlock_init (& pn -> hash_lock );
1164+ spin_lock_init (& pn -> hash_lock );
11531165
11541166 pde = proc_create_net ("pppoe" , 0444 , net -> proc_net ,
11551167 & pppoe_seq_ops , sizeof (struct seq_net_private ));
0 commit comments