diff options
author | Benjamin Thery <benjamin.thery@bull.net> | 2008-03-26 19:53:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-26 19:53:30 -0400 |
commit | 5983a3dff0036d7ef6a2139473564f4f3e7b2a11 (patch) | |
tree | 257abe1624f6bcbf7cc542bda87732e960ee3223 | |
parent | 60e8fbc4c53d3ef0cbffa393a9e7b77e2a1bae58 (diff) |
[NETNS][IPV6] flowlabels - make proc per namespace
Make /proc/net/ip6_flowlabel show only flow labels belonging to the
current network namespace.
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/ip6_flowlabel.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 78d1d913e36c..eb7a940310f4 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -611,6 +611,7 @@ done: | |||
611 | #ifdef CONFIG_PROC_FS | 611 | #ifdef CONFIG_PROC_FS |
612 | 612 | ||
613 | struct ip6fl_iter_state { | 613 | struct ip6fl_iter_state { |
614 | struct seq_net_private p; | ||
614 | int bucket; | 615 | int bucket; |
615 | }; | 616 | }; |
616 | 617 | ||
@@ -620,12 +621,15 @@ static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq) | |||
620 | { | 621 | { |
621 | struct ip6_flowlabel *fl = NULL; | 622 | struct ip6_flowlabel *fl = NULL; |
622 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | 623 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); |
624 | struct net *net = seq_file_net(seq); | ||
623 | 625 | ||
624 | for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) { | 626 | for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) { |
625 | if (fl_ht[state->bucket]) { | 627 | fl = fl_ht[state->bucket]; |
626 | fl = fl_ht[state->bucket]; | 628 | |
629 | while (fl && fl->fl_net != net) | ||
630 | fl = fl->next; | ||
631 | if (fl) | ||
627 | break; | 632 | break; |
628 | } | ||
629 | } | 633 | } |
630 | return fl; | 634 | return fl; |
631 | } | 635 | } |
@@ -633,12 +637,18 @@ static struct ip6_flowlabel *ip6fl_get_first(struct seq_file *seq) | |||
633 | static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flowlabel *fl) | 637 | static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flowlabel *fl) |
634 | { | 638 | { |
635 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | 639 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); |
640 | struct net *net = seq_file_net(seq); | ||
636 | 641 | ||
637 | fl = fl->next; | 642 | fl = fl->next; |
643 | try_again: | ||
644 | while (fl && fl->fl_net != net) | ||
645 | fl = fl->next; | ||
646 | |||
638 | while (!fl) { | 647 | while (!fl) { |
639 | if (++state->bucket <= FL_HASH_MASK) | 648 | if (++state->bucket <= FL_HASH_MASK) { |
640 | fl = fl_ht[state->bucket]; | 649 | fl = fl_ht[state->bucket]; |
641 | else | 650 | goto try_again; |
651 | } else | ||
642 | break; | 652 | break; |
643 | } | 653 | } |
644 | return fl; | 654 | return fl; |
@@ -708,8 +718,8 @@ static const struct seq_operations ip6fl_seq_ops = { | |||
708 | 718 | ||
709 | static int ip6fl_seq_open(struct inode *inode, struct file *file) | 719 | static int ip6fl_seq_open(struct inode *inode, struct file *file) |
710 | { | 720 | { |
711 | return seq_open_private(file, &ip6fl_seq_ops, | 721 | return seq_open_net(inode, file, &ip6fl_seq_ops, |
712 | sizeof(struct ip6fl_iter_state)); | 722 | sizeof(struct ip6fl_iter_state)); |
713 | } | 723 | } |
714 | 724 | ||
715 | static const struct file_operations ip6fl_seq_fops = { | 725 | static const struct file_operations ip6fl_seq_fops = { |
@@ -717,12 +727,13 @@ static const struct file_operations ip6fl_seq_fops = { | |||
717 | .open = ip6fl_seq_open, | 727 | .open = ip6fl_seq_open, |
718 | .read = seq_read, | 728 | .read = seq_read, |
719 | .llseek = seq_lseek, | 729 | .llseek = seq_lseek, |
720 | .release = seq_release_private, | 730 | .release = seq_release_net, |
721 | }; | 731 | }; |
722 | 732 | ||
723 | static int ip6_flowlabel_proc_init(struct net *net) | 733 | static int ip6_flowlabel_proc_init(struct net *net) |
724 | { | 734 | { |
725 | if (!proc_net_fops_create(net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops)) | 735 | if (!proc_net_fops_create(net, "ip6_flowlabel", |
736 | S_IRUGO, &ip6fl_seq_fops)) | ||
726 | return -ENOMEM; | 737 | return -ENOMEM; |
727 | return 0; | 738 | return 0; |
728 | } | 739 | } |
@@ -745,25 +756,21 @@ static inline void ip6_flowlabel_proc_fini(struct net *net) | |||
745 | static inline void ip6_flowlabel_net_exit(struct net *net) | 756 | static inline void ip6_flowlabel_net_exit(struct net *net) |
746 | { | 757 | { |
747 | ip6_fl_purge(net); | 758 | ip6_fl_purge(net); |
759 | ip6_flowlabel_proc_fini(net); | ||
748 | } | 760 | } |
749 | 761 | ||
750 | static struct pernet_operations ip6_flowlabel_net_ops = { | 762 | static struct pernet_operations ip6_flowlabel_net_ops = { |
763 | .init = ip6_flowlabel_proc_init, | ||
751 | .exit = ip6_flowlabel_net_exit, | 764 | .exit = ip6_flowlabel_net_exit, |
752 | }; | 765 | }; |
753 | 766 | ||
754 | int ip6_flowlabel_init(void) | 767 | int ip6_flowlabel_init(void) |
755 | { | 768 | { |
756 | int err; | 769 | return register_pernet_subsys(&ip6_flowlabel_net_ops); |
757 | |||
758 | err = register_pernet_subsys(&ip6_flowlabel_net_ops); | ||
759 | if (err) | ||
760 | return err; | ||
761 | return ip6_flowlabel_proc_init(&init_net); | ||
762 | } | 770 | } |
763 | 771 | ||
764 | void ip6_flowlabel_cleanup(void) | 772 | void ip6_flowlabel_cleanup(void) |
765 | { | 773 | { |
766 | del_timer(&ip6_fl_gc_timer); | 774 | del_timer(&ip6_fl_gc_timer); |
767 | unregister_pernet_subsys(&ip6_flowlabel_net_ops); | 775 | unregister_pernet_subsys(&ip6_flowlabel_net_ops); |
768 | ip6_flowlabel_proc_fini(&init_net); | ||
769 | } | 776 | } |