From patchwork Mon Apr 16 11:39:38 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Schillstrom X-Patchwork-Id: 152819 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 956FBB7014 for ; Mon, 16 Apr 2012 21:54:49 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753508Ab2DPLyp (ORCPT ); Mon, 16 Apr 2012 07:54:45 -0400 Received: from mailgw1.ericsson.se ([193.180.251.45]:58257 "EHLO mailgw1.ericsson.se" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753438Ab2DPLyn (ORCPT ); Mon, 16 Apr 2012 07:54:43 -0400 X-Greylist: delayed 901 seconds by postgrey-1.27 at vger.kernel.org; Mon, 16 Apr 2012 07:54:42 EDT X-AuditID: c1b4fb2d-b7b76ae0000063d8-7f-4f8c04fb5cdc Received: from esessmw0191.eemea.ericsson.se (Unknown_Domain [153.88.253.125]) (using TLS with cipher AES128-SHA (AES128-SHA/128 bits)) (Client did not present a certificate) by mailgw1.ericsson.se (Symantec Mail Security) with SMTP id 3C.E2.25560.BF40C8F4; Mon, 16 Apr 2012 13:39:40 +0200 (CEST) Received: from seassled11.rnd.as.sw.ericsson.se (153.88.115.8) by esessmw0191.eemea.ericsson.se (153.88.115.85) with Microsoft SMTP Server id 8.3.213.0; Mon, 16 Apr 2012 13:39:39 +0200 Received: by seassled11.rnd.as.sw.ericsson.se (Postfix, from userid 88893) id 67D8040638D; Mon, 16 Apr 2012 13:39:39 +0200 (CEST) From: Hans Schillstrom To: , , , , , CC: , Hans Schillstrom Subject: [PATCH 2/2] IPVS: make failure of netns init more stable Date: Mon, 16 Apr 2012 13:39:38 +0200 Message-ID: <1334576378-2034-2-git-send-email-hans.schillstrom@ericsson.com> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <1334576378-2034-1-git-send-email-hans.schillstrom@ericsson.com> References: <1334576378-2034-1-git-send-email-hans.schillstrom@ericsson.com> MIME-Version: 1.0 X-Brightmail-Tracker: AAAAAA== Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Add a IP_VS_F_NET_INIT_OK flag that other modules can use for check of a successful init of ip_vs Signed-off-by: Hans Schillstrom --- include/net/ip_vs.h | 20 +++++++++++++++++++- net/netfilter/ipvs/ip_vs_conn.c | 2 +- net/netfilter/ipvs/ip_vs_core.c | 15 +++++++++------ net/netfilter/ipvs/ip_vs_ctl.c | 2 +- net/netfilter/ipvs/ip_vs_ftp.c | 2 ++ net/netfilter/ipvs/ip_vs_lblc.c | 3 +++ net/netfilter/ipvs/ip_vs_lblcr.c | 3 +++ 7 files changed, 38 insertions(+), 9 deletions(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 04e2211..96add20 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -787,7 +787,8 @@ struct ip_vs_app { /* IPVS in network namespace */ struct netns_ipvs { int gen; /* Generation */ - int enable; /* enable like nf_hooks do */ + /* Status flags: enable like nf_hooks, and netns init ok */ + int status; /* * Hash table: for real service lookups */ @@ -909,6 +910,23 @@ struct netns_ipvs { struct net *net; /* Needed by timer routines */ }; +/* + * Status flags for each netns + */ +enum { + IP_VS_ENABLE, /* Enabled ipvs i.e. service registered */ + IP_VS_NET_INIT_OK, /* Netns init is OK */ + IP_VS_F_ENABLE = (1 << IP_VS_ENABLE), + IP_VS_F_NET_INIT_OK = (1 << IP_VS_NET_INIT_OK) +}; + +#define IS_IPVS_ENABLED(ipvs) (ipvs->status & IP_VS_F_ENABLE) +#define IPVS_ENABLE(ipvs) (ipvs->status |= IP_VS_F_ENABLE) +#define IPVS_DISABLE(ipvs) (ipvs->status &= ~IP_VS_F_ENABLE) + +#define IS_IPVS_NETNS_OK(ipvs) (ipvs->status & IP_VS_F_NET_INIT_OK) +#define IPVS_NETNS_OK(ipvs) (ipvs->status |= IP_VS_F_NET_INIT_OK) + #define DEFAULT_SYNC_THRESHOLD 3 #define DEFAULT_SYNC_PERIOD 50 #define DEFAULT_SYNC_VER 1 diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 4a09b78..4f2a7ec 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -783,7 +783,7 @@ static void ip_vs_conn_expire(unsigned long data) * conntrack cleanup for the net. */ smp_rmb(); - if (ipvs->enable) + if (IS_IPVS_ENABLED(ipvs)) ip_vs_conn_drop_conntrack(cp); } diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index b5a5c73..58722a2 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1112,7 +1112,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) return NF_ACCEPT; net = skb_net(skb); - if (!net_ipvs(net)->enable) + if (!IS_IPVS_ENABLED(net_ipvs(net))) return NF_ACCEPT; ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); @@ -1513,7 +1513,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) } /* ipvs enabled in this netns ? */ net = skb_net(skb); - if (!net_ipvs(net)->enable) + if (!IS_IPVS_ENABLED(net_ipvs(net))) return NF_ACCEPT; ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); @@ -1735,7 +1735,7 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb, /* ipvs enabled in this netns ? */ net = skb_net(skb); - if (!net_ipvs(net)->enable) + if (!IS_IPVS_ENABLED(net_ipvs(net))) return NF_ACCEPT; return ip_vs_in_icmp(skb, &r, hooknum); @@ -1755,7 +1755,7 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb, /* ipvs enabled in this netns ? */ net = skb_net(skb); - if (!net_ipvs(net)->enable) + if (!IS_IPVS_ENABLED(net_ipvs(net))) return NF_ACCEPT; return ip_vs_in_icmp_v6(skb, &r, hooknum); @@ -1881,7 +1881,7 @@ static int __net_init __ip_vs_init(struct net *net) return -ENOMEM; /* Hold the beast until a service is registerd */ - ipvs->enable = 0; + ipvs->status = 0; ipvs->net = net; /* Counters used for creating unique names */ ipvs->gen = atomic_read(&ipvs_netns_cnt); @@ -1906,6 +1906,7 @@ static int __net_init __ip_vs_init(struct net *net) if (ip_vs_sync_net_init(net) < 0) goto sync_fail; + IPVS_NETNS_OK(ipvs); printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n", sizeof(struct netns_ipvs), ipvs->gen); return 0; @@ -1924,6 +1925,7 @@ protocol_fail: control_fail: ip_vs_estimator_net_cleanup(net); estimator_fail: + ipvs->status = 0; /* Nothing is enabled */ return -ENOMEM; } @@ -1936,12 +1938,13 @@ static void __net_exit __ip_vs_cleanup(struct net *net) ip_vs_control_net_cleanup(net); ip_vs_estimator_net_cleanup(net); IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen); + net->ipvs = NULL; } static void __net_exit __ip_vs_dev_cleanup(struct net *net) { EnterFunction(2); - net_ipvs(net)->enable = 0; /* Disable packet reception */ + IPVS_DISABLE(net_ipvs(net)); /* Disable packet reception */ smp_wmb(); ip_vs_sync_net_cleanup(net); LeaveFunction(2); diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index b8d0df7..5392de9 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1221,7 +1221,7 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, *svc_p = svc; /* Now there is a service - full throttle */ - ipvs->enable = 1; + IPVS_ENABLE(ipvs); return 0; diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c index debb8c7..6bc2420 100644 --- a/net/netfilter/ipvs/ip_vs_ftp.c +++ b/net/netfilter/ipvs/ip_vs_ftp.c @@ -439,6 +439,8 @@ static int __net_init __ip_vs_ftp_init(struct net *net) struct ip_vs_app *app; struct netns_ipvs *ipvs = net_ipvs(net); + if (!IS_IPVS_NETNS_OK(ipvs)) + return -EUNATCH; app = kmemdup(&ip_vs_ftp, sizeof(struct ip_vs_app), GFP_KERNEL); if (!app) return -ENOMEM; diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index 27c24f1..f158f0c 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c @@ -551,6 +551,9 @@ static int __net_init __ip_vs_lblc_init(struct net *net) { struct netns_ipvs *ipvs = net_ipvs(net); + if (!IS_IPVS_NETNS_OK(ipvs)) + return -EUNATCH; + if (!net_eq(net, &init_net)) { ipvs->lblc_ctl_table = kmemdup(vs_vars_table, sizeof(vs_vars_table), diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index 7498756..aeecda4 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c @@ -745,6 +745,9 @@ static int __net_init __ip_vs_lblcr_init(struct net *net) { struct netns_ipvs *ipvs = net_ipvs(net); + if (!IS_IPVS_NETNS_OK(ipvs)) + return -EUNATCH; + if (!net_eq(net, &init_net)) { ipvs->lblcr_ctl_table = kmemdup(vs_vars_table, sizeof(vs_vars_table),