- Update to 3.4-rc6.
[linux-flexiantxendom0-3.2.10.git] / net / netfilter / ipvs / ip_vs_proto.c
index f843a88..ed835e6 100644 (file)
@@ -59,9 +59,6 @@ static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp)
        return 0;
 }
 
-#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP) || \
-    defined(CONFIG_IP_VS_PROTO_SCTP) || defined(CONFIG_IP_VS_PROTO_AH) || \
-    defined(CONFIG_IP_VS_PROTO_ESP)
 /*
  *     register an ipvs protocols netns related data
  */
@@ -81,12 +78,18 @@ register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp)
        ipvs->proto_data_table[hash] = pd;
        atomic_set(&pd->appcnt, 0);     /* Init app counter */
 
-       if (pp->init_netns != NULL)
-               pp->init_netns(net, pd);
+       if (pp->init_netns != NULL) {
+               int ret = pp->init_netns(net, pd);
+               if (ret) {
+                       /* unlink an free proto data */
+                       ipvs->proto_data_table[hash] = pd->next;
+                       kfree(pd);
+                       return ret;
+               }
+       }
 
        return 0;
 }
-#endif
 
 /*
  *     unregister an ipvs protocol
@@ -316,22 +319,35 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
  */
 int __net_init ip_vs_protocol_net_init(struct net *net)
 {
+       int i, ret;
+       static struct ip_vs_protocol *protos[] = {
 #ifdef CONFIG_IP_VS_PROTO_TCP
-       register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp);
+        &ip_vs_protocol_tcp,
 #endif
 #ifdef CONFIG_IP_VS_PROTO_UDP
-       register_ip_vs_proto_netns(net, &ip_vs_protocol_udp);
+       &ip_vs_protocol_udp,
 #endif
 #ifdef CONFIG_IP_VS_PROTO_SCTP
-       register_ip_vs_proto_netns(net, &ip_vs_protocol_sctp);
+       &ip_vs_protocol_sctp,
 #endif
 #ifdef CONFIG_IP_VS_PROTO_AH
-       register_ip_vs_proto_netns(net, &ip_vs_protocol_ah);
+       &ip_vs_protocol_ah,
 #endif
 #ifdef CONFIG_IP_VS_PROTO_ESP
-       register_ip_vs_proto_netns(net, &ip_vs_protocol_esp);
+       &ip_vs_protocol_esp,
 #endif
+       };
+
+       for (i = 0; i < ARRAY_SIZE(protos); i++) {
+               ret = register_ip_vs_proto_netns(net, protos[i]);
+               if (ret < 0)
+                       goto cleanup;
+       }
        return 0;
+
+cleanup:
+       ip_vs_protocol_net_cleanup(net);
+       return ret;
 }
 
 void __net_exit ip_vs_protocol_net_cleanup(struct net *net)