#endif
 
-void __init ip6_route_init(void)
+int __init ip6_route_init(void)
 {
+       int ret;
+
        ip6_dst_ops.kmem_cachep =
                kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
                                  SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
        ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops.kmem_cachep;
 
-       fib6_init();
-       proc_net_fops_create(&init_net, "ipv6_route", 0, &ipv6_route_proc_fops);
-       proc_net_fops_create(&init_net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops);
+       ret = fib6_init();
+       if (ret)
+               goto out_kmem_cache;
+
+#ifdef CONFIG_PROC_FS
+       ret = -ENOMEM;
+       if (!proc_net_fops_create(&init_net, "ipv6_route",
+                                 0, &ipv6_route_proc_fops))
+               goto out_fib6_init;
+
+       if (!proc_net_fops_create(&init_net, "rt6_stats",
+                                 S_IRUGO, &rt6_stats_seq_fops))
+               goto out_proc_ipv6_route;
+#endif
+
 #ifdef CONFIG_XFRM
-       xfrm6_init();
+       ret = xfrm6_init();
+       if (ret)
+               goto out_proc_rt6_stats;
 #endif
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
-       fib6_rules_init();
+       ret = fib6_rules_init();
+       if (ret)
+               goto xfrm6_init;
 #endif
+       ret = -ENOBUFS;
+       if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) ||
+           __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) ||
+           __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL))
+               goto fib6_rules_init;
 
-       __rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL);
-       __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL);
-       __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL);
+       ret = 0;
+out:
+       return ret;
+
+fib6_rules_init:
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+       fib6_rules_cleanup();
+xfrm6_init:
+#endif
+#ifdef CONFIG_XFRM
+       xfrm6_fini();
+out_proc_rt6_stats:
+#endif
+#ifdef CONFIG_PROC_FS
+       proc_net_remove(&init_net, "rt6_stats");
+out_proc_ipv6_route:
+       proc_net_remove(&init_net, "ipv6_route");
+out_fib6_init:
+#endif
+       rt6_ifdown(NULL);
+       fib6_gc_cleanup();
+out_kmem_cache:
+       kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
+       goto out;
 }
 
 void ip6_route_cleanup(void)
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
        fib6_rules_cleanup();
 #endif
-#ifdef CONFIG_PROC_FS
        proc_net_remove(&init_net, "ipv6_route");
        proc_net_remove(&init_net, "rt6_stats");
-#endif
 #ifdef CONFIG_XFRM
        xfrm6_fini();
 #endif