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