@@ -182,21 +182,47 @@ void rose_kill_by_neigh(struct rose_neigh *neigh)
182182 */
183183static void rose_kill_by_device (struct net_device * dev )
184184{
185- struct sock * s ;
185+ struct sock * sk , * array [16 ];
186+ struct rose_sock * rose ;
187+ bool rescan ;
188+ int i , cnt ;
186189
190+ start :
191+ rescan = false;
192+ cnt = 0 ;
187193 spin_lock_bh (& rose_list_lock );
188- sk_for_each (s , & rose_list ) {
189- struct rose_sock * rose = rose_sk (s );
194+ sk_for_each (sk , & rose_list ) {
195+ rose = rose_sk (sk );
196+ if (rose -> device == dev ) {
197+ if (cnt == ARRAY_SIZE (array )) {
198+ rescan = true;
199+ break ;
200+ }
201+ sock_hold (sk );
202+ array [cnt ++ ] = sk ;
203+ }
204+ }
205+ spin_unlock_bh (& rose_list_lock );
190206
207+ for (i = 0 ; i < cnt ; i ++ ) {
208+ sk = array [cnt ];
209+ rose = rose_sk (sk );
210+ lock_sock (sk );
211+ spin_lock_bh (& rose_list_lock );
191212 if (rose -> device == dev ) {
192- rose_disconnect (s , ENETUNREACH , ROSE_OUT_OF_ORDER , 0 );
213+ rose_disconnect (sk , ENETUNREACH , ROSE_OUT_OF_ORDER , 0 );
193214 if (rose -> neighbour )
194215 rose -> neighbour -> use -- ;
195216 netdev_put (rose -> device , & rose -> dev_tracker );
196217 rose -> device = NULL ;
197218 }
219+ spin_unlock_bh (& rose_list_lock );
220+ release_sock (sk );
221+ sock_put (sk );
222+ cond_resched ();
198223 }
199- spin_unlock_bh (& rose_list_lock );
224+ if (rescan )
225+ goto start ;
200226}
201227
202228/*
@@ -656,7 +682,10 @@ static int rose_release(struct socket *sock)
656682 break ;
657683 }
658684
685+ spin_lock_bh (& rose_list_lock );
659686 netdev_put (rose -> device , & rose -> dev_tracker );
687+ rose -> device = NULL ;
688+ spin_unlock_bh (& rose_list_lock );
660689 sock -> sk = NULL ;
661690 release_sock (sk );
662691 sock_put (sk );
0 commit comments