@@ -355,25 +355,52 @@ static void **alloc_pg_vec(struct netlink_sock *nlk,
355
355
return NULL ;
356
356
}
357
357
358
+
359
+ static void
360
+ __netlink_set_ring (struct sock * sk , struct nl_mmap_req * req , bool tx_ring , void * * pg_vec ,
361
+ unsigned int order )
362
+ {
363
+ struct netlink_sock * nlk = nlk_sk (sk );
364
+ struct sk_buff_head * queue ;
365
+ struct netlink_ring * ring ;
366
+
367
+ queue = tx_ring ? & sk -> sk_write_queue : & sk -> sk_receive_queue ;
368
+ ring = tx_ring ? & nlk -> tx_ring : & nlk -> rx_ring ;
369
+
370
+ spin_lock_bh (& queue -> lock );
371
+
372
+ ring -> frame_max = req -> nm_frame_nr - 1 ;
373
+ ring -> head = 0 ;
374
+ ring -> frame_size = req -> nm_frame_size ;
375
+ ring -> pg_vec_pages = req -> nm_block_size / PAGE_SIZE ;
376
+
377
+ swap (ring -> pg_vec_len , req -> nm_block_nr );
378
+ swap (ring -> pg_vec_order , order );
379
+ swap (ring -> pg_vec , pg_vec );
380
+
381
+ __skb_queue_purge (queue );
382
+ spin_unlock_bh (& queue -> lock );
383
+
384
+ WARN_ON (atomic_read (& nlk -> mapped ));
385
+
386
+ if (pg_vec )
387
+ free_pg_vec (pg_vec , order , req -> nm_block_nr );
388
+ }
389
+
358
390
static int netlink_set_ring (struct sock * sk , struct nl_mmap_req * req ,
359
- bool closing , bool tx_ring )
391
+ bool tx_ring )
360
392
{
361
393
struct netlink_sock * nlk = nlk_sk (sk );
362
394
struct netlink_ring * ring ;
363
- struct sk_buff_head * queue ;
364
395
void * * pg_vec = NULL ;
365
396
unsigned int order = 0 ;
366
- int err ;
367
397
368
398
ring = tx_ring ? & nlk -> tx_ring : & nlk -> rx_ring ;
369
- queue = tx_ring ? & sk -> sk_write_queue : & sk -> sk_receive_queue ;
370
399
371
- if (!closing ) {
372
- if (atomic_read (& nlk -> mapped ))
373
- return - EBUSY ;
374
- if (atomic_read (& ring -> pending ))
375
- return - EBUSY ;
376
- }
400
+ if (atomic_read (& nlk -> mapped ))
401
+ return - EBUSY ;
402
+ if (atomic_read (& ring -> pending ))
403
+ return - EBUSY ;
377
404
378
405
if (req -> nm_block_nr ) {
379
406
if (ring -> pg_vec != NULL )
@@ -405,31 +432,19 @@ static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req,
405
432
return - EINVAL ;
406
433
}
407
434
408
- err = - EBUSY ;
409
435
mutex_lock (& nlk -> pg_vec_lock );
410
- if (closing || atomic_read (& nlk -> mapped ) == 0 ) {
411
- err = 0 ;
412
- spin_lock_bh (& queue -> lock );
413
-
414
- ring -> frame_max = req -> nm_frame_nr - 1 ;
415
- ring -> head = 0 ;
416
- ring -> frame_size = req -> nm_frame_size ;
417
- ring -> pg_vec_pages = req -> nm_block_size / PAGE_SIZE ;
418
-
419
- swap (ring -> pg_vec_len , req -> nm_block_nr );
420
- swap (ring -> pg_vec_order , order );
421
- swap (ring -> pg_vec , pg_vec );
422
-
423
- __skb_queue_purge (queue );
424
- spin_unlock_bh (& queue -> lock );
425
-
426
- WARN_ON (atomic_read (& nlk -> mapped ));
436
+ if (atomic_read (& nlk -> mapped ) == 0 ) {
437
+ __netlink_set_ring (sk , req , tx_ring , pg_vec , order );
438
+ mutex_unlock (& nlk -> pg_vec_lock );
439
+ return 0 ;
427
440
}
441
+
428
442
mutex_unlock (& nlk -> pg_vec_lock );
429
443
430
444
if (pg_vec )
431
445
free_pg_vec (pg_vec , order , req -> nm_block_nr );
432
- return err ;
446
+
447
+ return - EBUSY ;
433
448
}
434
449
435
450
static void netlink_mm_open (struct vm_area_struct * vma )
@@ -898,10 +913,10 @@ static void netlink_sock_destruct(struct sock *sk)
898
913
899
914
memset (& req , 0 , sizeof (req ));
900
915
if (nlk -> rx_ring .pg_vec )
901
- netlink_set_ring (sk , & req , true, false );
916
+ __netlink_set_ring (sk , & req , false, NULL , 0 );
902
917
memset (& req , 0 , sizeof (req ));
903
918
if (nlk -> tx_ring .pg_vec )
904
- netlink_set_ring (sk , & req , true, true );
919
+ __netlink_set_ring (sk , & req , true, NULL , 0 );
905
920
}
906
921
#endif /* CONFIG_NETLINK_MMAP */
907
922
@@ -2197,7 +2212,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
2197
2212
return - EINVAL ;
2198
2213
if (copy_from_user (& req , optval , sizeof (req )))
2199
2214
return - EFAULT ;
2200
- err = netlink_set_ring (sk , & req , false,
2215
+ err = netlink_set_ring (sk , & req ,
2201
2216
optname == NETLINK_TX_RING );
2202
2217
break ;
2203
2218
}
0 commit comments