diff options
author | Wang Chen <wangchen@cn.fujitsu.com> | 2008-07-03 00:13:30 -0400 |
---|---|---|
committer | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2008-07-03 04:51:56 -0400 |
commit | 623d1a1af77bd52a389c6eda5920e28eb2ee468b (patch) | |
tree | 85d0a7fbcd83b5a2cacf50b24a66c0063f7eca07 | |
parent | dd3abc4ef52597ec8268274222574b2700ba3ded (diff) |
ipv6: Do cleanup for ip6_mr_init.
If do not do it, we will get following issues:
1. Leaving junks after inet6_init failing halfway.
2. Leaving proc and notifier junks after ipv6 modules unloading.
Signed-off-by: Wang Chen <wangchen@cn.fujitsu.com>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
-rw-r--r-- | include/linux/mroute6.h | 3 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 11 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 38 |
3 files changed, 45 insertions, 7 deletions
diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h index e7989593142b..4c4d6f57d5c5 100644 --- a/include/linux/mroute6.h +++ b/include/linux/mroute6.h | |||
@@ -135,7 +135,8 @@ extern int ip6_mroute_setsockopt(struct sock *, int, char __user *, int); | |||
135 | extern int ip6_mroute_getsockopt(struct sock *, int, char __user *, int __user *); | 135 | extern int ip6_mroute_getsockopt(struct sock *, int, char __user *, int __user *); |
136 | extern int ip6_mr_input(struct sk_buff *skb); | 136 | extern int ip6_mr_input(struct sk_buff *skb); |
137 | extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg); | 137 | extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg); |
138 | extern void ip6_mr_init(void); | 138 | extern int ip6_mr_init(void); |
139 | extern void ip6_mr_cleanup(void); | ||
139 | 140 | ||
140 | struct mif_device | 141 | struct mif_device |
141 | { | 142 | { |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3ce8d2f318c6..6b39af1acb5e 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -953,7 +953,9 @@ static int __init inet6_init(void) | |||
953 | if (err) | 953 | if (err) |
954 | goto icmp_fail; | 954 | goto icmp_fail; |
955 | #ifdef CONFIG_IPV6_MROUTE | 955 | #ifdef CONFIG_IPV6_MROUTE |
956 | ip6_mr_init(); | 956 | err = ip6_mr_init(); |
957 | if (err) | ||
958 | goto ipmr_fail; | ||
957 | #endif | 959 | #endif |
958 | err = ndisc_init(); | 960 | err = ndisc_init(); |
959 | if (err) | 961 | if (err) |
@@ -1057,6 +1059,10 @@ netfilter_fail: | |||
1057 | igmp_fail: | 1059 | igmp_fail: |
1058 | ndisc_cleanup(); | 1060 | ndisc_cleanup(); |
1059 | ndisc_fail: | 1061 | ndisc_fail: |
1062 | #ifdef CONFIG_IPV6_MROUTE | ||
1063 | ip6_mr_cleanup(); | ||
1064 | ipmr_fail: | ||
1065 | #endif | ||
1060 | icmpv6_cleanup(); | 1066 | icmpv6_cleanup(); |
1061 | icmp_fail: | 1067 | icmp_fail: |
1062 | unregister_pernet_subsys(&inet6_net_ops); | 1068 | unregister_pernet_subsys(&inet6_net_ops); |
@@ -1111,6 +1117,9 @@ static void __exit inet6_exit(void) | |||
1111 | ipv6_netfilter_fini(); | 1117 | ipv6_netfilter_fini(); |
1112 | igmp6_cleanup(); | 1118 | igmp6_cleanup(); |
1113 | ndisc_cleanup(); | 1119 | ndisc_cleanup(); |
1120 | #ifdef CONFIG_IPV6_MROUTE | ||
1121 | ip6_mr_cleanup(); | ||
1122 | #endif | ||
1114 | icmpv6_cleanup(); | 1123 | icmpv6_cleanup(); |
1115 | rawv6_exit(); | 1124 | rawv6_exit(); |
1116 | 1125 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 90e763073dc5..cfac26d674ed 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -948,23 +948,51 @@ static struct notifier_block ip6_mr_notifier = { | |||
948 | * Setup for IP multicast routing | 948 | * Setup for IP multicast routing |
949 | */ | 949 | */ |
950 | 950 | ||
951 | void __init ip6_mr_init(void) | 951 | int __init ip6_mr_init(void) |
952 | { | 952 | { |
953 | int err; | ||
954 | |||
953 | mrt_cachep = kmem_cache_create("ip6_mrt_cache", | 955 | mrt_cachep = kmem_cache_create("ip6_mrt_cache", |
954 | sizeof(struct mfc6_cache), | 956 | sizeof(struct mfc6_cache), |
955 | 0, SLAB_HWCACHE_ALIGN, | 957 | 0, SLAB_HWCACHE_ALIGN, |
956 | NULL); | 958 | NULL); |
957 | if (!mrt_cachep) | 959 | if (!mrt_cachep) |
958 | panic("cannot allocate ip6_mrt_cache"); | 960 | return -ENOMEM; |
959 | 961 | ||
960 | setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); | 962 | setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); |
961 | register_netdevice_notifier(&ip6_mr_notifier); | 963 | err = register_netdevice_notifier(&ip6_mr_notifier); |
964 | if (err) | ||
965 | goto reg_notif_fail; | ||
966 | #ifdef CONFIG_PROC_FS | ||
967 | err = -ENOMEM; | ||
968 | if (!proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops)) | ||
969 | goto proc_vif_fail; | ||
970 | if (!proc_net_fops_create(&init_net, "ip6_mr_cache", | ||
971 | 0, &ip6mr_mfc_fops)) | ||
972 | goto proc_cache_fail; | ||
973 | #endif | ||
974 | return 0; | ||
975 | reg_notif_fail: | ||
976 | kmem_cache_destroy(mrt_cachep); | ||
962 | #ifdef CONFIG_PROC_FS | 977 | #ifdef CONFIG_PROC_FS |
963 | proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops); | 978 | proc_vif_fail: |
964 | proc_net_fops_create(&init_net, "ip6_mr_cache", 0, &ip6mr_mfc_fops); | 979 | unregister_netdevice_notifier(&ip6_mr_notifier); |
980 | proc_cache_fail: | ||
981 | proc_net_remove(&init_net, "ip6_mr_vif"); | ||
965 | #endif | 982 | #endif |
983 | return err; | ||
966 | } | 984 | } |
967 | 985 | ||
986 | void ip6_mr_cleanup(void) | ||
987 | { | ||
988 | #ifdef CONFIG_PROC_FS | ||
989 | proc_net_remove(&init_net, "ip6_mr_cache"); | ||
990 | proc_net_remove(&init_net, "ip6_mr_vif"); | ||
991 | #endif | ||
992 | unregister_netdevice_notifier(&ip6_mr_notifier); | ||
993 | del_timer(&ipmr_expire_timer); | ||
994 | kmem_cache_destroy(mrt_cachep); | ||
995 | } | ||
968 | 996 | ||
969 | static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock) | 997 | static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock) |
970 | { | 998 | { |