Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2773

kernel-2.6.18-238.el5.src.rpm

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)