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>
This commit is contained in:
Hannes Frederic Sowa
2013-09-21 16:55:59 +02:00
committed by David S. Miller
parent 6229ed1f22
commit 8d2ca1d7b5
3 changed files with 175 additions and 68 deletions

View File

@@ -2800,56 +2800,12 @@ static int ip6_route_dev_notify(struct notifier_block *this,
#ifdef CONFIG_PROC_FS
struct rt6_proc_arg
{
char *buffer;
int offset;
int length;
int skip;
int len;
};
static int rt6_info_route(struct rt6_info *rt, void *p_arg)
{
struct seq_file *m = p_arg;
seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen);
#ifdef CONFIG_IPV6_SUBTREES
seq_printf(m, "%pi6 %02x ", &rt->rt6i_src.addr, rt->rt6i_src.plen);
#else
seq_puts(m, "00000000000000000000000000000000 00 ");
#endif
if (rt->rt6i_flags & RTF_GATEWAY) {
seq_printf(m, "%pi6", &rt->rt6i_gateway);
} else {
seq_puts(m, "00000000000000000000000000000000");
}
seq_printf(m, " %08x %08x %08x %08x %8s\n",
rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
rt->dst.__use, rt->rt6i_flags,
rt->dst.dev ? rt->dst.dev->name : "");
return 0;
}
static int ipv6_route_show(struct seq_file *m, void *v)
{
struct net *net = (struct net *)m->private;
fib6_clean_all_ro(net, rt6_info_route, 0, m);
return 0;
}
static int ipv6_route_open(struct inode *inode, struct file *file)
{
return single_open_net(inode, file, ipv6_route_show);
}
static const struct file_operations ipv6_route_proc_fops = {
.owner = THIS_MODULE,
.open = ipv6_route_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release_net,
.release = seq_release_net,
};
static int rt6_stats_seq_show(struct seq_file *seq, void *v)