@@ -281,88 +281,136 @@ void sctp_eps_proc_exit(struct net *net)
281
281
remove_proc_entry ("eps" , net -> sctp .proc_net_sctp );
282
282
}
283
283
284
+ struct sctp_ht_iter {
285
+ struct seq_net_private p ;
286
+ struct rhashtable_iter hti ;
287
+ };
284
288
285
- static void * sctp_assocs_seq_start (struct seq_file * seq , loff_t * pos )
289
+ static struct sctp_transport * sctp_transport_get_next (struct seq_file * seq )
286
290
{
287
- if ( * pos >= sctp_assoc_hashsize )
288
- return NULL ;
291
+ struct sctp_ht_iter * iter = seq -> private ;
292
+ struct sctp_transport * t ;
289
293
290
- if (* pos < 0 )
291
- * pos = 0 ;
294
+ t = rhashtable_walk_next (& iter -> hti );
295
+ for (; t ; t = rhashtable_walk_next (& iter -> hti )) {
296
+ if (IS_ERR (t )) {
297
+ if (PTR_ERR (t ) == - EAGAIN )
298
+ continue ;
299
+ break ;
300
+ }
292
301
293
- if (* pos == 0 )
294
- seq_printf (seq , " ASSOC SOCK STY SST ST HBKT "
295
- "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
296
- "RPORT LADDRS <-> RADDRS "
297
- "HBINT INS OUTS MAXRT T1X T2X RTXC "
298
- "wmema wmemq sndbuf rcvbuf\n" );
302
+ if (net_eq (sock_net (t -> asoc -> base .sk ), seq_file_net (seq )) &&
303
+ t -> asoc -> peer .primary_path == t )
304
+ break ;
305
+ }
299
306
300
- return ( void * ) pos ;
307
+ return t ;
301
308
}
302
309
303
- static void sctp_assocs_seq_stop (struct seq_file * seq , void * v )
310
+ static struct sctp_transport * sctp_transport_get_idx (struct seq_file * seq ,
311
+ loff_t pos )
312
+ {
313
+ void * obj ;
314
+
315
+ while (pos && (obj = sctp_transport_get_next (seq )) && !IS_ERR (obj ))
316
+ pos -- ;
317
+
318
+ return obj ;
319
+ }
320
+
321
+ static int sctp_transport_walk_start (struct seq_file * seq )
304
322
{
323
+ struct sctp_ht_iter * iter = seq -> private ;
324
+ int err ;
325
+
326
+ err = rhashtable_walk_init (& sctp_transport_hashtable , & iter -> hti );
327
+ if (err )
328
+ return err ;
329
+
330
+ err = rhashtable_walk_start (& iter -> hti );
331
+
332
+ return err == - EAGAIN ? 0 : err ;
305
333
}
306
334
335
+ static void sctp_transport_walk_stop (struct seq_file * seq )
336
+ {
337
+ struct sctp_ht_iter * iter = seq -> private ;
338
+
339
+ rhashtable_walk_stop (& iter -> hti );
340
+ rhashtable_walk_exit (& iter -> hti );
341
+ }
342
+
343
+ static void * sctp_assocs_seq_start (struct seq_file * seq , loff_t * pos )
344
+ {
345
+ int err = sctp_transport_walk_start (seq );
346
+
347
+ if (err )
348
+ return ERR_PTR (err );
349
+
350
+ return * pos ? sctp_transport_get_idx (seq , * pos ) : SEQ_START_TOKEN ;
351
+ }
352
+
353
+ static void sctp_assocs_seq_stop (struct seq_file * seq , void * v )
354
+ {
355
+ sctp_transport_walk_stop (seq );
356
+ }
307
357
308
358
static void * sctp_assocs_seq_next (struct seq_file * seq , void * v , loff_t * pos )
309
359
{
310
- if (++ * pos >= sctp_assoc_hashsize )
311
- return NULL ;
360
+ ++ * pos ;
312
361
313
- return pos ;
362
+ return sctp_transport_get_next ( seq ) ;
314
363
}
315
364
316
365
/* Display sctp associations (/proc/net/sctp/assocs). */
317
366
static int sctp_assocs_seq_show (struct seq_file * seq , void * v )
318
367
{
319
- struct sctp_hashbucket * head ;
320
- struct sctp_ep_common * epb ;
368
+ struct sctp_transport * transport ;
321
369
struct sctp_association * assoc ;
370
+ struct sctp_ep_common * epb ;
322
371
struct sock * sk ;
323
- int hash = * (loff_t * )v ;
324
-
325
- if (hash >= sctp_assoc_hashsize )
326
- return - ENOMEM ;
327
372
328
- head = & sctp_assoc_hashtable [hash ];
329
- local_bh_disable ();
330
- read_lock (& head -> lock );
331
- sctp_for_each_hentry (epb , & head -> chain ) {
332
- assoc = sctp_assoc (epb );
333
- sk = epb -> sk ;
334
- if (!net_eq (sock_net (sk ), seq_file_net (seq )))
335
- continue ;
336
- seq_printf (seq ,
337
- "%8pK %8pK %-3d %-3d %-2d %-4d "
338
- "%4d %8d %8d %7u %5lu %-5d %5d " ,
339
- assoc , sk , sctp_sk (sk )-> type , sk -> sk_state ,
340
- assoc -> state , hash ,
341
- assoc -> assoc_id ,
342
- assoc -> sndbuf_used ,
343
- atomic_read (& assoc -> rmem_alloc ),
344
- from_kuid_munged (seq_user_ns (seq ), sock_i_uid (sk )),
345
- sock_i_ino (sk ),
346
- epb -> bind_addr .port ,
347
- assoc -> peer .port );
348
- seq_printf (seq , " " );
349
- sctp_seq_dump_local_addrs (seq , epb );
350
- seq_printf (seq , "<-> " );
351
- sctp_seq_dump_remote_addrs (seq , assoc );
352
- seq_printf (seq , "\t%8lu %5d %5d %4d %4d %4d %8d "
353
- "%8d %8d %8d %8d" ,
354
- assoc -> hbinterval , assoc -> c .sinit_max_instreams ,
355
- assoc -> c .sinit_num_ostreams , assoc -> max_retrans ,
356
- assoc -> init_retries , assoc -> shutdown_retries ,
357
- assoc -> rtx_data_chunks ,
358
- atomic_read (& sk -> sk_wmem_alloc ),
359
- sk -> sk_wmem_queued ,
360
- sk -> sk_sndbuf ,
361
- sk -> sk_rcvbuf );
362
- seq_printf (seq , "\n" );
373
+ if (v == SEQ_START_TOKEN ) {
374
+ seq_printf (seq , " ASSOC SOCK STY SST ST HBKT "
375
+ "ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
376
+ "RPORT LADDRS <-> RADDRS "
377
+ "HBINT INS OUTS MAXRT T1X T2X RTXC "
378
+ "wmema wmemq sndbuf rcvbuf\n" );
379
+ return 0 ;
363
380
}
364
- read_unlock (& head -> lock );
365
- local_bh_enable ();
381
+
382
+ transport = (struct sctp_transport * )v ;
383
+ assoc = transport -> asoc ;
384
+ epb = & assoc -> base ;
385
+ sk = epb -> sk ;
386
+
387
+ seq_printf (seq ,
388
+ "%8pK %8pK %-3d %-3d %-2d %-4d "
389
+ "%4d %8d %8d %7u %5lu %-5d %5d " ,
390
+ assoc , sk , sctp_sk (sk )-> type , sk -> sk_state ,
391
+ assoc -> state , 0 ,
392
+ assoc -> assoc_id ,
393
+ assoc -> sndbuf_used ,
394
+ atomic_read (& assoc -> rmem_alloc ),
395
+ from_kuid_munged (seq_user_ns (seq ), sock_i_uid (sk )),
396
+ sock_i_ino (sk ),
397
+ epb -> bind_addr .port ,
398
+ assoc -> peer .port );
399
+ seq_printf (seq , " " );
400
+ sctp_seq_dump_local_addrs (seq , epb );
401
+ seq_printf (seq , "<-> " );
402
+ sctp_seq_dump_remote_addrs (seq , assoc );
403
+ seq_printf (seq , "\t%8lu %5d %5d %4d %4d %4d %8d "
404
+ "%8d %8d %8d %8d" ,
405
+ assoc -> hbinterval , assoc -> c .sinit_max_instreams ,
406
+ assoc -> c .sinit_num_ostreams , assoc -> max_retrans ,
407
+ assoc -> init_retries , assoc -> shutdown_retries ,
408
+ assoc -> rtx_data_chunks ,
409
+ atomic_read (& sk -> sk_wmem_alloc ),
410
+ sk -> sk_wmem_queued ,
411
+ sk -> sk_sndbuf ,
412
+ sk -> sk_rcvbuf );
413
+ seq_printf (seq , "\n" );
366
414
367
415
return 0 ;
368
416
}
@@ -378,7 +426,7 @@ static const struct seq_operations sctp_assoc_ops = {
378
426
static int sctp_assocs_seq_open (struct inode * inode , struct file * file )
379
427
{
380
428
return seq_open_net (inode , file , & sctp_assoc_ops ,
381
- sizeof (struct seq_net_private ));
429
+ sizeof (struct sctp_ht_iter ));
382
430
}
383
431
384
432
static const struct file_operations sctp_assocs_seq_fops = {
@@ -409,112 +457,94 @@ void sctp_assocs_proc_exit(struct net *net)
409
457
410
458
static void * sctp_remaddr_seq_start (struct seq_file * seq , loff_t * pos )
411
459
{
412
- if (* pos >= sctp_assoc_hashsize )
413
- return NULL ;
414
-
415
- if (* pos < 0 )
416
- * pos = 0 ;
460
+ int err = sctp_transport_walk_start (seq );
417
461
418
- if (* pos == 0 )
419
- seq_printf (seq , "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
420
- "REM_ADDR_RTX START STATE\n" );
462
+ if (err )
463
+ return ERR_PTR (err );
421
464
422
- return ( void * ) pos ;
465
+ return * pos ? sctp_transport_get_idx ( seq , * pos ) : SEQ_START_TOKEN ;
423
466
}
424
467
425
468
static void * sctp_remaddr_seq_next (struct seq_file * seq , void * v , loff_t * pos )
426
469
{
427
- if (++ * pos >= sctp_assoc_hashsize )
428
- return NULL ;
470
+ ++ * pos ;
429
471
430
- return pos ;
472
+ return sctp_transport_get_next ( seq ) ;
431
473
}
432
474
433
475
static void sctp_remaddr_seq_stop (struct seq_file * seq , void * v )
434
476
{
477
+ sctp_transport_walk_stop (seq );
435
478
}
436
479
437
480
static int sctp_remaddr_seq_show (struct seq_file * seq , void * v )
438
481
{
439
- struct sctp_hashbucket * head ;
440
- struct sctp_ep_common * epb ;
441
482
struct sctp_association * assoc ;
442
483
struct sctp_transport * tsp ;
443
- int hash = * (loff_t * )v ;
444
484
445
- if (hash >= sctp_assoc_hashsize )
446
- return - ENOMEM ;
485
+ if (v == SEQ_START_TOKEN ) {
486
+ seq_printf (seq , "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
487
+ "REM_ADDR_RTX START STATE\n" );
488
+ return 0 ;
489
+ }
447
490
448
- head = & sctp_assoc_hashtable [ hash ] ;
449
- local_bh_disable () ;
450
- read_lock ( & head -> lock );
451
- rcu_read_lock ();
452
- sctp_for_each_hentry ( epb , & head -> chain ) {
453
- if (! net_eq ( sock_net ( epb -> sk ), seq_file_net ( seq )) )
491
+ tsp = ( struct sctp_transport * ) v ;
492
+ assoc = tsp -> asoc ;
493
+
494
+ list_for_each_entry_rcu ( tsp , & assoc -> peer . transport_addr_list ,
495
+ transports ) {
496
+ if (tsp -> dead )
454
497
continue ;
455
- assoc = sctp_assoc (epb );
456
- list_for_each_entry_rcu (tsp , & assoc -> peer .transport_addr_list ,
457
- transports ) {
458
- if (tsp -> dead )
459
- continue ;
498
+ /*
499
+ * The remote address (ADDR)
500
+ */
501
+ tsp -> af_specific -> seq_dump_addr (seq , & tsp -> ipaddr );
502
+ seq_printf (seq , " " );
503
+ /*
504
+ * The association ID (ASSOC_ID)
505
+ */
506
+ seq_printf (seq , "%d " , tsp -> asoc -> assoc_id );
507
+
508
+ /*
509
+ * If the Heartbeat is active (HB_ACT)
510
+ * Note: 1 = Active, 0 = Inactive
511
+ */
512
+ seq_printf (seq , "%d " , timer_pending (& tsp -> hb_timer ));
513
+
514
+ /*
515
+ * Retransmit time out (RTO)
516
+ */
517
+ seq_printf (seq , "%lu " , tsp -> rto );
518
+
519
+ /*
520
+ * Maximum path retransmit count (PATH_MAX_RTX)
521
+ */
522
+ seq_printf (seq , "%d " , tsp -> pathmaxrxt );
523
+
524
+ /*
525
+ * remote address retransmit count (REM_ADDR_RTX)
526
+ * Note: We don't have a way to tally this at the moment
527
+ * so lets just leave it as zero for the moment
528
+ */
529
+ seq_puts (seq , "0 " );
530
+
531
+ /*
532
+ * remote address start time (START). This is also not
533
+ * currently implemented, but we can record it with a
534
+ * jiffies marker in a subsequent patch
535
+ */
536
+ seq_puts (seq , "0 " );
537
+
538
+ /*
539
+ * The current state of this destination. I.e.
540
+ * SCTP_ACTIVE, SCTP_INACTIVE, ...
541
+ */
542
+ seq_printf (seq , "%d" , tsp -> state );
460
543
461
- /*
462
- * The remote address (ADDR)
463
- */
464
- tsp -> af_specific -> seq_dump_addr (seq , & tsp -> ipaddr );
465
- seq_printf (seq , " " );
466
-
467
- /*
468
- * The association ID (ASSOC_ID)
469
- */
470
- seq_printf (seq , "%d " , tsp -> asoc -> assoc_id );
471
-
472
- /*
473
- * If the Heartbeat is active (HB_ACT)
474
- * Note: 1 = Active, 0 = Inactive
475
- */
476
- seq_printf (seq , "%d " , timer_pending (& tsp -> hb_timer ));
477
-
478
- /*
479
- * Retransmit time out (RTO)
480
- */
481
- seq_printf (seq , "%lu " , tsp -> rto );
482
-
483
- /*
484
- * Maximum path retransmit count (PATH_MAX_RTX)
485
- */
486
- seq_printf (seq , "%d " , tsp -> pathmaxrxt );
487
-
488
- /*
489
- * remote address retransmit count (REM_ADDR_RTX)
490
- * Note: We don't have a way to tally this at the moment
491
- * so lets just leave it as zero for the moment
492
- */
493
- seq_puts (seq , "0 " );
494
-
495
- /*
496
- * remote address start time (START). This is also not
497
- * currently implemented, but we can record it with a
498
- * jiffies marker in a subsequent patch
499
- */
500
- seq_puts (seq , "0 " );
501
-
502
- /*
503
- * The current state of this destination. I.e.
504
- * SCTP_ACTIVE, SCTP_INACTIVE, ...
505
- */
506
- seq_printf (seq , "%d" , tsp -> state );
507
-
508
- seq_printf (seq , "\n" );
509
- }
544
+ seq_printf (seq , "\n" );
510
545
}
511
546
512
- rcu_read_unlock ();
513
- read_unlock (& head -> lock );
514
- local_bh_enable ();
515
-
516
547
return 0 ;
517
-
518
548
}
519
549
520
550
static const struct seq_operations sctp_remaddr_ops = {
@@ -533,7 +563,7 @@ void sctp_remaddr_proc_exit(struct net *net)
533
563
static int sctp_remaddr_seq_open (struct inode * inode , struct file * file )
534
564
{
535
565
return seq_open_net (inode , file , & sctp_remaddr_ops ,
536
- sizeof (struct seq_net_private ));
566
+ sizeof (struct sctp_ht_iter ));
537
567
}
538
568
539
569
static const struct file_operations sctp_remaddr_seq_fops = {
0 commit comments