@@ -182,21 +182,47 @@ void rose_kill_by_neigh(struct rose_neigh *neigh)
182
182
*/
183
183
static void rose_kill_by_device (struct net_device * dev )
184
184
{
185
- struct sock * s ;
185
+ struct sock * sk , * array [16 ];
186
+ struct rose_sock * rose ;
187
+ bool rescan ;
188
+ int i , cnt ;
186
189
190
+ start :
191
+ rescan = false;
192
+ cnt = 0 ;
187
193
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 );
190
206
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 );
191
212
if (rose -> device == dev ) {
192
- rose_disconnect (s , ENETUNREACH , ROSE_OUT_OF_ORDER , 0 );
213
+ rose_disconnect (sk , ENETUNREACH , ROSE_OUT_OF_ORDER , 0 );
193
214
if (rose -> neighbour )
194
215
rose -> neighbour -> use -- ;
195
216
netdev_put (rose -> device , & rose -> dev_tracker );
196
217
rose -> device = NULL ;
197
218
}
219
+ spin_unlock_bh (& rose_list_lock );
220
+ release_sock (sk );
221
+ sock_put (sk );
222
+ cond_resched ();
198
223
}
199
- spin_unlock_bh (& rose_list_lock );
224
+ if (rescan )
225
+ goto start ;
200
226
}
201
227
202
228
/*
@@ -656,7 +682,10 @@ static int rose_release(struct socket *sock)
656
682
break ;
657
683
}
658
684
685
+ spin_lock_bh (& rose_list_lock );
659
686
netdev_put (rose -> device , & rose -> dev_tracker );
687
+ rose -> device = NULL ;
688
+ spin_unlock_bh (& rose_list_lock );
660
689
sock -> sk = NULL ;
661
690
release_sock (sk );
662
691
sock_put (sk );
0 commit comments