From: Amerigo Wang <amwang@redhat.com> Date: Tue, 19 Jan 2010 10:07:58 -0500 Subject: [net] ipv6: don't panic when kmem_cache_create fails Message-id: <20100119101118.4385.57232.sendpatchset@localhost.localdomain> Patchwork-id: 22646 O-Subject: [PATCH RHEL5] route6/fib6: don't panic when kmem_cache_create fails Bugzilla: 555338 RH-Acked-by: Neil Horman <nhorman@redhat.com> RH-Acked-by: David S. Miller <davem@redhat.com> RH-Acked-by: Thomas Graf <tgraf@redhat.com> BZ: https://bugzilla.redhat.com/show_bug.cgi?id=555338 Description: If the kmem_cache_create fails, the kernel will panic. It is acceptable if the system is booting. but if the ipv6 protocol is compiled as a module and it is loaded after the system has booted, we don't want to panic instead of just failing to initialize the protocol. The init function is now returning an error and the error is checked for protocol initialization. So the ipv6 protocol will fail safely. Upstream status: http://marc.info/?l=linux-netdev&m=119695007508858&w=2 Patch is directly from the customer. It looks fine for me too. Signed-off-by: WANG Cong <amwang@redhat.com> diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 72c7655..b23eca3 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -231,7 +231,7 @@ extern void fib6_run_gc(unsigned long dummy); extern void fib6_gc_cleanup(void); -extern void fib6_init(void); +extern int fib6_init(void); extern void fib6_rules_init(void); extern void fib6_rules_cleanup(void); diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index ceb5fc7..bff447f 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -59,7 +59,7 @@ extern struct dst_entry * ip6_route_output(struct sock *sk, extern int ip6_route_me_harder(struct sk_buff *skb); -extern void ip6_route_init(void); +extern int ip6_route_init(void); extern void ip6_route_cleanup(void); extern int ipv6_route_ioctl(unsigned int cmd, void __user *arg); diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 45371b9..44354a8 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -861,7 +861,10 @@ static int __init inet6_init(void) if (if6_proc_init()) goto proc_if6_fail; #endif - ip6_route_init(); + err = ip6_route_init(); + if (err) + goto route_fail; + ip6_flowlabel_init(); err = addrconf_init(); if (err) @@ -886,6 +889,7 @@ out: addrconf_fail: ip6_flowlabel_cleanup(); ip6_route_cleanup(); +route_fail: #ifdef CONFIG_PROC_FS if6_proc_exit(); proc_if6_fail: diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 0606560..902a1c5 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1452,16 +1452,18 @@ void fib6_run_gc(unsigned long dummy) spin_unlock_bh(&fib6_gc_lock); } -void __init fib6_init(void) +int __init fib6_init(void) { fib6_node_kmem = kmem_cache_create("fib6_nodes", sizeof(struct fib6_node), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (!fib6_node_kmem) - panic("cannot create fib6_nodes cache"); + return -ENOMEM; fib6_tables_init(); + + return 0; } void fib6_gc_cleanup(void) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 616f682..87a1d5c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2477,7 +2477,7 @@ ctl_table ipv6_route_table[] = { #endif -void __init ip6_route_init(void) +int __init ip6_route_init(void) { struct proc_dir_entry *p; @@ -2486,11 +2486,15 @@ void __init ip6_route_init(void) 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (!ip6_dst_ops.kmem_cachep) - panic("cannot create ip6_dst_cache"); + return -ENOMEM; ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep; - fib6_init(); + if (fib6_init()) { + kmem_cache_destroy(ip6_dst_ops.kmem_cachep); + return -ENOMEM; + } + #ifdef CONFIG_PROC_FS p = proc_net_create("ipv6_route", 0, rt6_proc_info); if (p) @@ -2504,6 +2508,7 @@ void __init ip6_route_init(void) #ifdef CONFIG_IPV6_MULTIPLE_TABLES fib6_rules_init(); #endif + return 0; } void ip6_route_cleanup(void)