diff options
author | Hannes Frederic Sowa <hannes@stressinduktion.org> | 2013-09-21 10:55:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-09-27 17:32:16 -0400 |
commit | 8d2ca1d7b5c3e63b3a8a81ae99015b615c5f2bf7 (patch) | |
tree | 37202066f7715ffc4858c4dd9b5c66c1c8c5cd76 /net/ipv6/route.c | |
parent | 6229ed1f22592d5ee8360a638cb965fef88b080f (diff) |
ipv6: avoid high order memory allocations for /proc/net/ipv6_route
Dumping routes on a system with lots rt6_infos in the fibs causes up to
11-order allocations in seq_file (which fail). While we could switch
there to vmalloc we could just implement the streaming interface for
/proc/net/ipv6_route. This patch switches /proc/net/ipv6_route from
single_open_net to seq_open_net.
loff_t *pos tracks dst entries.
Also kill never used struct rt6_proc_arg and now unused function
fib6_clean_all_ro.
Cc: Ben Greear <greearb@candelatech.com>
Cc: Patrick McHardy <kaber@trash.net>
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 46 |
1 files changed, 1 insertions, 45 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c979dd96d82a..aa901bb60cf2 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2800,56 +2800,12 @@ static int ip6_route_dev_notify(struct notifier_block *this, | |||
2800 | 2800 | ||
2801 | #ifdef CONFIG_PROC_FS | 2801 | #ifdef CONFIG_PROC_FS |
2802 | 2802 | ||
2803 | struct rt6_proc_arg | ||
2804 | { | ||
2805 | char *buffer; | ||
2806 | int offset; | ||
2807 | int length; | ||
2808 | int skip; | ||
2809 | int len; | ||
2810 | }; | ||
2811 | |||
2812 | static int rt6_info_route(struct rt6_info *rt, void *p_arg) | ||
2813 | { | ||
2814 | struct seq_file *m = p_arg; | ||
2815 | |||
2816 | seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen); | ||
2817 | |||
2818 | #ifdef CONFIG_IPV6_SUBTREES | ||
2819 | seq_printf(m, "%pi6 %02x ", &rt->rt6i_src.addr, rt->rt6i_src.plen); | ||
2820 | #else | ||
2821 | seq_puts(m, "00000000000000000000000000000000 00 "); | ||
2822 | #endif | ||
2823 | if (rt->rt6i_flags & RTF_GATEWAY) { | ||
2824 | seq_printf(m, "%pi6", &rt->rt6i_gateway); | ||
2825 | } else { | ||
2826 | seq_puts(m, "00000000000000000000000000000000"); | ||
2827 | } | ||
2828 | seq_printf(m, " %08x %08x %08x %08x %8s\n", | ||
2829 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), | ||
2830 | rt->dst.__use, rt->rt6i_flags, | ||
2831 | rt->dst.dev ? rt->dst.dev->name : ""); | ||
2832 | return 0; | ||
2833 | } | ||
2834 | |||
2835 | static int ipv6_route_show(struct seq_file *m, void *v) | ||
2836 | { | ||
2837 | struct net *net = (struct net *)m->private; | ||
2838 | fib6_clean_all_ro(net, rt6_info_route, 0, m); | ||
2839 | return 0; | ||
2840 | } | ||
2841 | |||
2842 | static int ipv6_route_open(struct inode *inode, struct file *file) | ||
2843 | { | ||
2844 | return single_open_net(inode, file, ipv6_route_show); | ||
2845 | } | ||
2846 | |||
2847 | static const struct file_operations ipv6_route_proc_fops = { | 2803 | static const struct file_operations ipv6_route_proc_fops = { |
2848 | .owner = THIS_MODULE, | 2804 | .owner = THIS_MODULE, |
2849 | .open = ipv6_route_open, | 2805 | .open = ipv6_route_open, |
2850 | .read = seq_read, | 2806 | .read = seq_read, |
2851 | .llseek = seq_lseek, | 2807 | .llseek = seq_lseek, |
2852 | .release = single_release_net, | 2808 | .release = seq_release_net, |
2853 | }; | 2809 | }; |
2854 | 2810 | ||
2855 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) | 2811 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) |