diff options
author | Denis V. Lunev <den@openvz.org> | 2008-02-29 11:14:50 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-02-29 11:14:50 -0800 |
commit | a5710d6582868a96cf0fe02eac11d34cfbc783c9 (patch) | |
tree | 8fcc3f4bc58436c1809602a98c9ce759c74f9410 | |
parent | 9b0f976f27f00a81cf47643d90854659626795b4 (diff) |
[ICMP]: Add return code to icmp_init.
icmp_init could fail and this is normal for namespace other than initial.
So, the panic should be triggered only on init_net initialization path.
Additionally create rollback path for icmp_init as a separate function.
It will also be used later during namespace destruction.
Signed-off-by: Denis V. Lunev <den@openvz.org>
Acked-by: Daniel Lezcano <dlezcano@fr.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/icmp.h | 2 | ||||
-rw-r--r-- | net/ipv4/af_inet.c | 3 | ||||
-rw-r--r-- | net/ipv4/icmp.c | 26 |
3 files changed, 25 insertions, 6 deletions
diff --git a/include/net/icmp.h b/include/net/icmp.h index 7bf714d9d7c..faba64db8ff 100644 --- a/include/net/icmp.h +++ b/include/net/icmp.h @@ -48,7 +48,7 @@ struct sk_buff; extern void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info); extern int icmp_rcv(struct sk_buff *skb); extern int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg); -extern void icmp_init(void); +extern int icmp_init(void); extern void icmp_out_count(unsigned char type); /* Move into dst.h ? */ diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index a7a99ac856d..4f539bd4871 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1430,7 +1430,8 @@ static int __init inet_init(void) * Set the ICMP layer up */ - icmp_init(); + if (icmp_init() < 0) + panic("Failed to create the ICMP control socket.\n"); /* * Initialise the multicast router diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 98372db66c6..b345b3d9bca 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -1139,19 +1139,32 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = { }, }; -void __init icmp_init(void) +static void __exit icmp_exit(void) { - struct inet_sock *inet; int i; for_each_possible_cpu(i) { - int err; + struct socket *sock; + + sock = per_cpu(__icmp_socket, i); + if (sock == NULL) + continue; + per_cpu(__icmp_socket, i) = NULL; + sock_release(sock); + } +} +int __init icmp_init(void) +{ + struct inet_sock *inet; + int i, err; + + for_each_possible_cpu(i) { err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP, &per_cpu(__icmp_socket, i)); if (err < 0) - panic("Failed to create the ICMP control socket.\n"); + goto fail; per_cpu(__icmp_socket, i)->sk->sk_allocation = GFP_ATOMIC; @@ -1171,6 +1184,11 @@ void __init icmp_init(void) */ per_cpu(__icmp_socket, i)->sk->sk_prot->unhash(per_cpu(__icmp_socket, i)->sk); } + return 0; + +fail: + icmp_exit(); + return err; } EXPORT_SYMBOL(icmp_err_convert); |