diff options
author | Pavel Emelyanov <xemul@openvz.org> | 2008-07-18 07:05:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-18 07:05:17 -0400 |
commit | 7b7a9dfdf6ccda647f54ea5fa3bd0ac17a189eeb (patch) | |
tree | 92ab52ffab8bfdc1f3697ff8d02c12a06a43d76c | |
parent | d89cbbb1e69a3bfea38038fb058bd51013902ef3 (diff) |
proc: create /proc/net/netstat file in each net
Now all the shown in it statistics is netnsizated, time to
show it in appropriate net.
The appropriate net init/exit ops already exist - they make
the sockstat file per net - so just extend them.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/proc.c | 47 |
1 files changed, 38 insertions, 9 deletions
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index e11144b0134a..df8c4affde0f 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -413,6 +413,7 @@ static const struct file_operations snmp_seq_fops = { | |||
413 | static int netstat_seq_show(struct seq_file *seq, void *v) | 413 | static int netstat_seq_show(struct seq_file *seq, void *v) |
414 | { | 414 | { |
415 | int i; | 415 | int i; |
416 | struct net *net = seq->private; | ||
416 | 417 | ||
417 | seq_puts(seq, "TcpExt:"); | 418 | seq_puts(seq, "TcpExt:"); |
418 | for (i = 0; snmp4_net_list[i].name != NULL; i++) | 419 | for (i = 0; snmp4_net_list[i].name != NULL; i++) |
@@ -421,7 +422,7 @@ static int netstat_seq_show(struct seq_file *seq, void *v) | |||
421 | seq_puts(seq, "\nTcpExt:"); | 422 | seq_puts(seq, "\nTcpExt:"); |
422 | for (i = 0; snmp4_net_list[i].name != NULL; i++) | 423 | for (i = 0; snmp4_net_list[i].name != NULL; i++) |
423 | seq_printf(seq, " %lu", | 424 | seq_printf(seq, " %lu", |
424 | snmp_fold_field((void **)init_net.mib.net_statistics, | 425 | snmp_fold_field((void **)net->mib.net_statistics, |
425 | snmp4_net_list[i].entry)); | 426 | snmp4_net_list[i].entry)); |
426 | 427 | ||
427 | seq_puts(seq, "\nIpExt:"); | 428 | seq_puts(seq, "\nIpExt:"); |
@@ -431,7 +432,7 @@ static int netstat_seq_show(struct seq_file *seq, void *v) | |||
431 | seq_puts(seq, "\nIpExt:"); | 432 | seq_puts(seq, "\nIpExt:"); |
432 | for (i = 0; snmp4_ipextstats_list[i].name != NULL; i++) | 433 | for (i = 0; snmp4_ipextstats_list[i].name != NULL; i++) |
433 | seq_printf(seq, " %lu", | 434 | seq_printf(seq, " %lu", |
434 | snmp_fold_field((void **)init_net.mib.ip_statistics, | 435 | snmp_fold_field((void **)net->mib.ip_statistics, |
435 | snmp4_ipextstats_list[i].entry)); | 436 | snmp4_ipextstats_list[i].entry)); |
436 | 437 | ||
437 | seq_putc(seq, '\n'); | 438 | seq_putc(seq, '\n'); |
@@ -440,7 +441,32 @@ static int netstat_seq_show(struct seq_file *seq, void *v) | |||
440 | 441 | ||
441 | static int netstat_seq_open(struct inode *inode, struct file *file) | 442 | static int netstat_seq_open(struct inode *inode, struct file *file) |
442 | { | 443 | { |
443 | return single_open(file, netstat_seq_show, NULL); | 444 | int err; |
445 | struct net *net; | ||
446 | |||
447 | err = -ENXIO; | ||
448 | net = get_proc_net(inode); | ||
449 | if (net == NULL) | ||
450 | goto err_net; | ||
451 | |||
452 | err = single_open(file, netstat_seq_show, net); | ||
453 | if (err < 0) | ||
454 | goto err_open; | ||
455 | |||
456 | return 0; | ||
457 | |||
458 | err_open: | ||
459 | put_net(net); | ||
460 | err_net: | ||
461 | return err; | ||
462 | } | ||
463 | |||
464 | static int netstat_seq_release(struct inode *inode, struct file *file) | ||
465 | { | ||
466 | struct net *net = ((struct seq_file *)file->private_data)->private; | ||
467 | |||
468 | put_net(net); | ||
469 | return single_release(inode, file); | ||
444 | } | 470 | } |
445 | 471 | ||
446 | static const struct file_operations netstat_seq_fops = { | 472 | static const struct file_operations netstat_seq_fops = { |
@@ -448,18 +474,26 @@ static const struct file_operations netstat_seq_fops = { | |||
448 | .open = netstat_seq_open, | 474 | .open = netstat_seq_open, |
449 | .read = seq_read, | 475 | .read = seq_read, |
450 | .llseek = seq_lseek, | 476 | .llseek = seq_lseek, |
451 | .release = single_release, | 477 | .release = netstat_seq_release, |
452 | }; | 478 | }; |
453 | 479 | ||
454 | static __net_init int ip_proc_init_net(struct net *net) | 480 | static __net_init int ip_proc_init_net(struct net *net) |
455 | { | 481 | { |
456 | if (!proc_net_fops_create(net, "sockstat", S_IRUGO, &sockstat_seq_fops)) | 482 | if (!proc_net_fops_create(net, "sockstat", S_IRUGO, &sockstat_seq_fops)) |
457 | return -ENOMEM; | 483 | return -ENOMEM; |
484 | if (!proc_net_fops_create(net, "netstat", S_IRUGO, &netstat_seq_fops)) | ||
485 | goto out_netstat; | ||
486 | |||
458 | return 0; | 487 | return 0; |
488 | |||
489 | out_netstat: | ||
490 | proc_net_remove(net, "sockstat"); | ||
491 | return -ENOMEM; | ||
459 | } | 492 | } |
460 | 493 | ||
461 | static __net_exit void ip_proc_exit_net(struct net *net) | 494 | static __net_exit void ip_proc_exit_net(struct net *net) |
462 | { | 495 | { |
496 | proc_net_remove(net, "netstat"); | ||
463 | proc_net_remove(net, "sockstat"); | 497 | proc_net_remove(net, "sockstat"); |
464 | } | 498 | } |
465 | 499 | ||
@@ -475,16 +509,11 @@ int __init ip_misc_proc_init(void) | |||
475 | if (register_pernet_subsys(&ip_proc_ops)) | 509 | if (register_pernet_subsys(&ip_proc_ops)) |
476 | goto out_pernet; | 510 | goto out_pernet; |
477 | 511 | ||
478 | if (!proc_net_fops_create(&init_net, "netstat", S_IRUGO, &netstat_seq_fops)) | ||
479 | goto out_netstat; | ||
480 | |||
481 | if (!proc_net_fops_create(&init_net, "snmp", S_IRUGO, &snmp_seq_fops)) | 512 | if (!proc_net_fops_create(&init_net, "snmp", S_IRUGO, &snmp_seq_fops)) |
482 | goto out_snmp; | 513 | goto out_snmp; |
483 | out: | 514 | out: |
484 | return rc; | 515 | return rc; |
485 | out_snmp: | 516 | out_snmp: |
486 | proc_net_remove(&init_net, "netstat"); | ||
487 | out_netstat: | ||
488 | unregister_pernet_subsys(&ip_proc_ops); | 517 | unregister_pernet_subsys(&ip_proc_ops); |
489 | out_pernet: | 518 | out_pernet: |
490 | rc = -ENOMEM; | 519 | rc = -ENOMEM; |