* [v4 PATCH 1/6] IPVS: Change of socket usage to enable name space exit.
2011-05-01 16:50 [v2 PATCH 0/6] IPVS: init and cleanup Hans Schillstrom
@ 2011-05-01 16:50 ` Hans Schillstrom
2011-05-02 11:03 ` Simon Horman
2011-05-01 16:50 ` [v4 PATCH 2/6] IPVS: labels at pos 0 Hans Schillstrom
` (6 subsequent siblings)
7 siblings, 1 reply; 10+ messages in thread
From: Hans Schillstrom @ 2011-05-01 16:50 UTC (permalink / raw)
To: ja, horms, ebiederm, lvs-devel, netdev, netfilter-devel
Cc: hans.schillstrom, Hans Schillstrom
To work this patch also needs the other patches in this series.
VERSION: 4
DESCRIPTION
If the sync daemons run in a name space while it crashes
or get killed, there is no way to stop them except for a reboot.
When all patches are there, ip_vs_core will handle register_pernet_(),
i.e. ip_vs_sync_init() and ip_vs_sync_cleanup() will be removed.
Kernel threads should not increment the use count of a socket.
By calling sk_change_net() after creating a socket this is avoided.
sock_release cant be used intead sk_release_kernel() should be used.
Thanks Eric W Biederman for your advices.
This patch is based on net-next-2.6 ver 2.6.39-rc2
CHANGES
Rev 2
sock_create_kern() used instead of __sock_create()
return codes of kthread_stop() used.
Rev 3
-
Rev 4
Check of return code changed to -ESRCH in __ip_vs_sync_cleanup()
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Hans Schillstrom <hans@schillstrom.com>
---
net/netfilter/ipvs/ip_vs_core.c | 2 +-
net/netfilter/ipvs/ip_vs_sync.c | 58 +++++++++++++++++++++++++--------------
2 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 07accf6..a0791dc 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1896,7 +1896,7 @@ static int __net_init __ip_vs_init(struct net *net)
static void __net_exit __ip_vs_cleanup(struct net *net)
{
- IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen);
+ IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen);
}
static struct pernet_operations ipvs_core_ops = {
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 3e7961e..0cce953 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1303,13 +1303,18 @@ static struct socket *make_send_sock(struct net *net)
struct socket *sock;
int result;
- /* First create a socket */
- result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1);
+ /* First create a socket move it to right name space later */
+ result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
if (result < 0) {
pr_err("Error during creation of socket; terminating\n");
return ERR_PTR(result);
}
-
+ /*
+ * Kernel sockets that are a part of a namespace, should not
+ * hold a reference to a namespace in order to allow to stop it.
+ * After sk_change_net should be released using sk_release_kernel.
+ */
+ sk_change_net(sock->sk, net);
result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn);
if (result < 0) {
pr_err("Error setting outbound mcast interface\n");
@@ -1334,8 +1339,8 @@ static struct socket *make_send_sock(struct net *net)
return sock;
- error:
- sock_release(sock);
+error:
+ sk_release_kernel(sock->sk);
return ERR_PTR(result);
}
@@ -1350,12 +1355,17 @@ static struct socket *make_receive_sock(struct net *net)
int result;
/* First create a socket */
- result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1);
+ result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
if (result < 0) {
pr_err("Error during creation of socket; terminating\n");
return ERR_PTR(result);
}
-
+ /*
+ * Kernel sockets that are a part of a namespace, should not
+ * hold a reference to a namespace in order to allow to stop it.
+ * After sk_change_net should be released using sk_release_kernel.
+ */
+ sk_change_net(sock->sk, net);
/* it is equivalent to the REUSEADDR option in user-space */
sock->sk->sk_reuse = 1;
@@ -1377,8 +1387,8 @@ static struct socket *make_receive_sock(struct net *net)
return sock;
- error:
- sock_release(sock);
+error:
+ sk_release_kernel(sock->sk);
return ERR_PTR(result);
}
@@ -1473,7 +1483,7 @@ static int sync_thread_master(void *data)
ip_vs_sync_buff_release(sb);
/* release the sending multicast socket */
- sock_release(tinfo->sock);
+ sk_release_kernel(tinfo->sock->sk);
kfree(tinfo);
return 0;
@@ -1513,7 +1523,7 @@ static int sync_thread_backup(void *data)
}
/* release the sending multicast socket */
- sock_release(tinfo->sock);
+ sk_release_kernel(tinfo->sock->sk);
kfree(tinfo->buf);
kfree(tinfo);
@@ -1601,7 +1611,7 @@ outtinfo:
outbuf:
kfree(buf);
outsocket:
- sock_release(sock);
+ sk_release_kernel(sock->sk);
out:
return result;
}
@@ -1610,6 +1620,7 @@ out:
int stop_sync_thread(struct net *net, int state)
{
struct netns_ipvs *ipvs = net_ipvs(net);
+ int retc = -EINVAL;
IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current));
@@ -1629,7 +1640,7 @@ int stop_sync_thread(struct net *net, int state)
spin_lock_bh(&ipvs->sync_lock);
ipvs->sync_state &= ~IP_VS_STATE_MASTER;
spin_unlock_bh(&ipvs->sync_lock);
- kthread_stop(ipvs->master_thread);
+ retc = kthread_stop(ipvs->master_thread);
ipvs->master_thread = NULL;
} else if (state == IP_VS_STATE_BACKUP) {
if (!ipvs->backup_thread)
@@ -1639,16 +1650,14 @@ int stop_sync_thread(struct net *net, int state)
task_pid_nr(ipvs->backup_thread));
ipvs->sync_state &= ~IP_VS_STATE_BACKUP;
- kthread_stop(ipvs->backup_thread);
+ retc = kthread_stop(ipvs->backup_thread);
ipvs->backup_thread = NULL;
- } else {
- return -EINVAL;
}
/* decrease the module use count */
ip_vs_use_count_dec();
- return 0;
+ return retc;
}
/*
@@ -1670,8 +1679,15 @@ static int __net_init __ip_vs_sync_init(struct net *net)
static void __ip_vs_sync_cleanup(struct net *net)
{
- stop_sync_thread(net, IP_VS_STATE_MASTER);
- stop_sync_thread(net, IP_VS_STATE_BACKUP);
+ int retc;
+
+ retc = stop_sync_thread(net, IP_VS_STATE_MASTER);
+ if (retc && retc != -ESRCH)
+ pr_err("Failed to stop Master Daemon\n");
+
+ retc = stop_sync_thread(net, IP_VS_STATE_BACKUP);
+ if (retc && retc != -ESRCH)
+ pr_err("Failed to stop Backup Daemon\n");
}
static struct pernet_operations ipvs_sync_ops = {
@@ -1682,10 +1698,10 @@ static struct pernet_operations ipvs_sync_ops = {
int __init ip_vs_sync_init(void)
{
- return register_pernet_subsys(&ipvs_sync_ops);
+ return register_pernet_device(&ipvs_sync_ops);
}
void ip_vs_sync_cleanup(void)
{
- unregister_pernet_subsys(&ipvs_sync_ops);
+ unregister_pernet_device(&ipvs_sync_ops);
}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [v4 PATCH 1/6] IPVS: Change of socket usage to enable name space exit.
2011-05-01 16:50 ` [v4 PATCH 1/6] IPVS: Change of socket usage to enable name space exit Hans Schillstrom
@ 2011-05-02 11:03 ` Simon Horman
0 siblings, 0 replies; 10+ messages in thread
From: Simon Horman @ 2011-05-02 11:03 UTC (permalink / raw)
To: Hans Schillstrom
Cc: ja, ebiederm, lvs-devel, netdev, netfilter-devel,
hans.schillstrom
On Sun, May 01, 2011 at 06:50:13PM +0200, Hans Schillstrom wrote:
> To work this patch also needs the other patches in this series.
Hi Hans,
could you explain the implications statement above?
What kind of behaviour might I expect if only this patch is applied?
I'm planning to push this and 2/6 for 2.6.39, and as we have
discussed (offline) that combination works. But from a bisection
point of view, this patch needs to not "blow up" if used by itself.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [v4 PATCH 2/6] IPVS: labels at pos 0
2011-05-01 16:50 [v2 PATCH 0/6] IPVS: init and cleanup Hans Schillstrom
2011-05-01 16:50 ` [v4 PATCH 1/6] IPVS: Change of socket usage to enable name space exit Hans Schillstrom
@ 2011-05-01 16:50 ` Hans Schillstrom
2011-05-01 16:50 ` [v4 PATCH 3/6] IPVS: init and cleanup restructuring Hans Schillstrom
` (5 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Hans Schillstrom @ 2011-05-01 16:50 UTC (permalink / raw)
To: ja, horms, ebiederm, lvs-devel, netdev, netfilter-devel
Cc: hans.schillstrom, Hans Schillstrom
Put goto labels at the beginig of row
acording to coding style example.
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Hans Schillstrom <hans@schillstrom.com>
---
net/netfilter/ipvs/ip_vs_core.c | 10 +++++-----
net/netfilter/ipvs/ip_vs_ctl.c | 8 ++++----
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index a0791dc..d536b51 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1388,7 +1388,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
verdict = NF_DROP;
}
- out:
+out:
__ip_vs_conn_put(cp);
return verdict;
@@ -1955,14 +1955,14 @@ static int __init ip_vs_init(void)
cleanup_sync:
ip_vs_sync_cleanup();
- cleanup_conn:
+cleanup_conn:
ip_vs_conn_cleanup();
- cleanup_app:
+cleanup_app:
ip_vs_app_cleanup();
- cleanup_protocol:
+cleanup_protocol:
ip_vs_protocol_cleanup();
ip_vs_control_cleanup();
- cleanup_estimator:
+cleanup_estimator:
ip_vs_estimator_cleanup();
unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
return ret;
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index ae47090..a31a70c 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1327,9 +1327,9 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
ip_vs_bind_pe(svc, pe);
}
- out_unlock:
+out_unlock:
write_unlock_bh(&__ip_vs_svc_lock);
- out:
+out:
ip_vs_scheduler_put(old_sched);
ip_vs_pe_put(old_pe);
return ret;
@@ -2387,7 +2387,7 @@ __ip_vs_get_service_entries(struct net *net,
count++;
}
}
- out:
+out:
return ret;
}
@@ -2625,7 +2625,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
ret = -EINVAL;
}
- out:
+out:
mutex_unlock(&__ip_vs_mutex);
return ret;
}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [v4 PATCH 3/6] IPVS: init and cleanup restructuring.
2011-05-01 16:50 [v2 PATCH 0/6] IPVS: init and cleanup Hans Schillstrom
2011-05-01 16:50 ` [v4 PATCH 1/6] IPVS: Change of socket usage to enable name space exit Hans Schillstrom
2011-05-01 16:50 ` [v4 PATCH 2/6] IPVS: labels at pos 0 Hans Schillstrom
@ 2011-05-01 16:50 ` Hans Schillstrom
2011-05-01 16:50 ` [v4 PATCH 4/6] IPVS: rename of netns init and cleanup functions Hans Schillstrom
` (4 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Hans Schillstrom @ 2011-05-01 16:50 UTC (permalink / raw)
To: ja, horms, ebiederm, lvs-devel, netdev, netfilter-devel
Cc: hans.schillstrom, Hans Schillstrom
REVISION 4
DESCRIPTION
This patch tries to restore the initial init and cleanup
sequences that was before namspace patch.
The number of calls to register_pernet_device have been
reduced to one for the ip_vs.ko
Schedulers still have their own calls.
This patch adds a function __ip_vs_service_cleanup()
and a throttle or actually on/off switch for
the netfilter hooks.
The nf hooks will be enabled when the first service is loaded
and disabled when the last service is removed or when a
namespace exit starts.
CHANGES
Rev 2
receivening av device events, suggested by Julian.
This change add 3 new functions ip_vs_dst_event()
ip_vs_svc_reset() and __ip_vs_dev_reset().
Rev 3
Throttle renamed to enable.
Comments from Julian implemented
Check enable in ip_vs_in, ip_vs_out and ip_vs_forward_icmp*
Remove in ip_vs_in_icmp*.
ip_vs_svc_reset() moved into ip_vs_dst_event().
ip_vs_service_cleanup() uses ip_vs_flush and mutex lock.
ip_vs_unlink_service_nolock() added.
Rev 4
ip_vs_unlink_service_nolock() removed
ip_vs_flush() reverted.
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Hans Schillstrom <hans@schillstrom.com>
---
include/net/ip_vs.h | 17 +++++
net/netfilter/ipvs/ip_vs_app.c | 15 +----
net/netfilter/ipvs/ip_vs_conn.c | 12 +---
net/netfilter/ipvs/ip_vs_core.c | 101 ++++++++++++++++++++++++++++---
net/netfilter/ipvs/ip_vs_ctl.c | 123 ++++++++++++++++++++++++++++++++------
net/netfilter/ipvs/ip_vs_est.c | 14 +----
net/netfilter/ipvs/ip_vs_proto.c | 11 +---
net/netfilter/ipvs/ip_vs_sync.c | 13 +---
8 files changed, 226 insertions(+), 80 deletions(-)
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index d516f00..86aefed 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -791,6 +791,7 @@ struct ip_vs_app {
/* IPVS in network namespace */
struct netns_ipvs {
int gen; /* Generation */
+ int enable; /* enable like nf_hooks do */
/*
* Hash table: for real service lookups
*/
@@ -1089,6 +1090,22 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp)
atomic_inc(&ctl_cp->n_control);
}
+/*
+ * IPVS netns init & cleanup functions
+ */
+extern int __ip_vs_estimator_init(struct net *net);
+extern int __ip_vs_control_init(struct net *net);
+extern int __ip_vs_protocol_init(struct net *net);
+extern int __ip_vs_app_init(struct net *net);
+extern int __ip_vs_conn_init(struct net *net);
+extern int __ip_vs_sync_init(struct net *net);
+extern void __ip_vs_conn_cleanup(struct net *net);
+extern void __ip_vs_app_cleanup(struct net *net);
+extern void __ip_vs_protocol_cleanup(struct net *net);
+extern void __ip_vs_control_cleanup(struct net *net);
+extern void __ip_vs_estimator_cleanup(struct net *net);
+extern void __ip_vs_sync_cleanup(struct net *net);
+extern void __ip_vs_service_cleanup(struct net *net);
/*
* IPVS application functions
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index 2dc6de1..51f3af7 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -576,7 +576,7 @@ static const struct file_operations ip_vs_app_fops = {
};
#endif
-static int __net_init __ip_vs_app_init(struct net *net)
+int __net_init __ip_vs_app_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -585,26 +585,17 @@ static int __net_init __ip_vs_app_init(struct net *net)
return 0;
}
-static void __net_exit __ip_vs_app_cleanup(struct net *net)
+void __net_exit __ip_vs_app_cleanup(struct net *net)
{
proc_net_remove(net, "ip_vs_app");
}
-static struct pernet_operations ip_vs_app_ops = {
- .init = __ip_vs_app_init,
- .exit = __ip_vs_app_cleanup,
-};
-
int __init ip_vs_app_init(void)
{
- int rv;
-
- rv = register_pernet_subsys(&ip_vs_app_ops);
- return rv;
+ return 0;
}
void ip_vs_app_cleanup(void)
{
- unregister_pernet_subsys(&ip_vs_app_ops);
}
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index c97bd45..d3fd91b 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -1258,22 +1258,17 @@ int __net_init __ip_vs_conn_init(struct net *net)
return 0;
}
-static void __net_exit __ip_vs_conn_cleanup(struct net *net)
+void __net_exit __ip_vs_conn_cleanup(struct net *net)
{
/* flush all the connection entries first */
ip_vs_conn_flush(net);
proc_net_remove(net, "ip_vs_conn");
proc_net_remove(net, "ip_vs_conn_sync");
}
-static struct pernet_operations ipvs_conn_ops = {
- .init = __ip_vs_conn_init,
- .exit = __ip_vs_conn_cleanup,
-};
int __init ip_vs_conn_init(void)
{
int idx;
- int retc;
/* Compute size and mask */
ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits;
@@ -1309,17 +1304,14 @@ int __init ip_vs_conn_init(void)
rwlock_init(&__ip_vs_conntbl_lock_array[idx].l);
}
- retc = register_pernet_subsys(&ipvs_conn_ops);
-
/* calculate the random value for connection hash */
get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd));
- return retc;
+ return 0;
}
void ip_vs_conn_cleanup(void)
{
- unregister_pernet_subsys(&ipvs_conn_ops);
/* Release the empty cache */
kmem_cache_destroy(ip_vs_conn_cachep);
vfree(ip_vs_conn_tab);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index d536b51..b9debc9 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1113,6 +1113,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
return NF_ACCEPT;
net = skb_net(skb);
+ if (!net_ipvs(net)->enable)
+ return NF_ACCEPT;
+
ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6) {
@@ -1343,6 +1346,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
return NF_ACCEPT; /* The packet looks wrong, ignore */
net = skb_net(skb);
+
pd = ip_vs_proto_data_get(net, cih->protocol);
if (!pd)
return NF_ACCEPT;
@@ -1529,6 +1533,11 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
IP_VS_DBG_ADDR(af, &iph.daddr), hooknum);
return NF_ACCEPT;
}
+ /* ipvs enabled in this netns ? */
+ net = skb_net(skb);
+ if (!net_ipvs(net)->enable)
+ return NF_ACCEPT;
+
ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
/* Bad... Do not break raw sockets */
@@ -1562,7 +1571,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
}
- net = skb_net(skb);
/* Protocol supported? */
pd = ip_vs_proto_data_get(net, iph.protocol);
if (unlikely(!pd))
@@ -1588,7 +1596,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
}
IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet");
- net = skb_net(skb);
ipvs = net_ipvs(net);
/* Check the server status */
if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
@@ -1743,10 +1750,16 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb,
int (*okfn)(struct sk_buff *))
{
int r;
+ struct net *net;
if (ip_hdr(skb)->protocol != IPPROTO_ICMP)
return NF_ACCEPT;
+ /* ipvs enabled in this netns ? */
+ net = skb_net(skb);
+ if (!net_ipvs(net)->enable)
+ return NF_ACCEPT;
+
return ip_vs_in_icmp(skb, &r, hooknum);
}
@@ -1757,10 +1770,16 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,
int (*okfn)(struct sk_buff *))
{
int r;
+ struct net *net;
if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6)
return NF_ACCEPT;
+ /* ipvs enabled in this netns ? */
+ net = skb_net(skb);
+ if (!net_ipvs(net)->enable)
+ return NF_ACCEPT;
+
return ip_vs_in_icmp_v6(skb, &r, hooknum);
}
#endif
@@ -1884,21 +1903,72 @@ static int __net_init __ip_vs_init(struct net *net)
pr_err("%s(): no memory.\n", __func__);
return -ENOMEM;
}
+ /* Hold the beast until a service is registerd */
+ ipvs->enable = 0;
ipvs->net = net;
/* Counters used for creating unique names */
ipvs->gen = atomic_read(&ipvs_netns_cnt);
atomic_inc(&ipvs_netns_cnt);
net->ipvs = ipvs;
+
+ if (__ip_vs_estimator_init(net) < 0)
+ goto estimator_fail;
+
+ if (__ip_vs_control_init(net) < 0)
+ goto control_fail;
+
+ if (__ip_vs_protocol_init(net) < 0)
+ goto protocol_fail;
+
+ if (__ip_vs_app_init(net) < 0)
+ goto app_fail;
+
+ if (__ip_vs_conn_init(net) < 0)
+ goto conn_fail;
+
+ if (__ip_vs_sync_init(net) < 0)
+ goto sync_fail;
+
printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n",
sizeof(struct netns_ipvs), ipvs->gen);
return 0;
+/*
+ * Error handling
+ */
+
+sync_fail:
+ __ip_vs_conn_cleanup(net);
+conn_fail:
+ __ip_vs_app_cleanup(net);
+app_fail:
+ __ip_vs_protocol_cleanup(net);
+protocol_fail:
+ __ip_vs_control_cleanup(net);
+control_fail:
+ __ip_vs_estimator_cleanup(net);
+estimator_fail:
+ return -ENOMEM;
}
static void __net_exit __ip_vs_cleanup(struct net *net)
{
+ __ip_vs_service_cleanup(net); /* ip_vs_flush() with locks */
+ __ip_vs_conn_cleanup(net);
+ __ip_vs_app_cleanup(net);
+ __ip_vs_protocol_cleanup(net);
+ __ip_vs_control_cleanup(net);
+ __ip_vs_estimator_cleanup(net);
IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen);
}
+static void __net_exit __ip_vs_dev_cleanup(struct net *net)
+{
+ EnterFunction(2);
+ net_ipvs(net)->enable = 0; /* Disable packet reception */
+ __ip_vs_sync_cleanup(net);
+ LeaveFunction(2);
+}
+
static struct pernet_operations ipvs_core_ops = {
.init = __ip_vs_init,
.exit = __ip_vs_cleanup,
@@ -1906,6 +1976,10 @@ static struct pernet_operations ipvs_core_ops = {
.size = sizeof(struct netns_ipvs),
};
+static struct pernet_operations ipvs_core_dev_ops = {
+ .exit = __ip_vs_dev_cleanup,
+};
+
/*
* Initialize IP Virtual Server
*/
@@ -1913,10 +1987,6 @@ static int __init ip_vs_init(void)
{
int ret;
- ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */
- if (ret < 0)
- return ret;
-
ip_vs_estimator_init();
ret = ip_vs_control_init();
if (ret < 0) {
@@ -1944,15 +2014,28 @@ static int __init ip_vs_init(void)
goto cleanup_conn;
}
+ ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */
+ if (ret < 0)
+ goto cleanup_sync;
+
+ ret = register_pernet_device(&ipvs_core_dev_ops);
+ if (ret < 0)
+ goto cleanup_sub;
+
ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
if (ret < 0) {
pr_err("can't register hooks.\n");
- goto cleanup_sync;
+ goto cleanup_dev;
}
pr_info("ipvs loaded.\n");
+
return ret;
+cleanup_dev:
+ unregister_pernet_device(&ipvs_core_dev_ops);
+cleanup_sub:
+ unregister_pernet_subsys(&ipvs_core_ops);
cleanup_sync:
ip_vs_sync_cleanup();
cleanup_conn:
@@ -1964,20 +2047,20 @@ cleanup_protocol:
ip_vs_control_cleanup();
cleanup_estimator:
ip_vs_estimator_cleanup();
- unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
return ret;
}
static void __exit ip_vs_cleanup(void)
{
nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
+ unregister_pernet_device(&ipvs_core_dev_ops);
+ unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
ip_vs_sync_cleanup();
ip_vs_conn_cleanup();
ip_vs_app_cleanup();
ip_vs_protocol_cleanup();
ip_vs_control_cleanup();
ip_vs_estimator_cleanup();
- unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
pr_info("ipvs unloaded.\n");
}
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index a31a70c..fe8891f 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -69,6 +69,11 @@ int ip_vs_get_debug_level(void)
}
#endif
+
+/* Protos */
+static void __ip_vs_del_service(struct ip_vs_service *svc);
+
+
#ifdef CONFIG_IP_VS_IPV6
/* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */
static int __ip_vs_addr_is_local_v6(struct net *net,
@@ -345,6 +350,9 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
svc->flags &= ~IP_VS_SVC_F_HASHED;
atomic_dec(&svc->refcnt);
+ /* No more services, no need for input */
+ if (atomic_read(&svc->refcnt) == 0)
+ net_ipvs(svc->net)->enable = 0;
return 1;
}
@@ -1214,6 +1222,8 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
write_unlock_bh(&__ip_vs_svc_lock);
*svc_p = svc;
+ /* Now there is a service - full throttle */
+ ipvs->enable = 1;
return 0;
@@ -1472,6 +1482,84 @@ static int ip_vs_flush(struct net *net)
return 0;
}
+/*
+ * Delete service by {netns} in the service table.
+ * Called by __ip_vs_cleanup()
+ */
+void __ip_vs_service_cleanup(struct net *net)
+{
+ EnterFunction(2);
+ /* Check for "full" addressed entries */
+ mutex_lock(&__ip_vs_mutex);
+ ip_vs_flush(net);
+ mutex_unlock(&__ip_vs_mutex);
+ LeaveFunction(2);
+}
+/*
+ * Release dst hold by dst_cache
+ */
+static inline void
+__ip_vs_dev_reset(struct ip_vs_dest *dest, struct net_device *dev)
+{
+ spin_lock_bh(&dest->dst_lock);
+ if (dest->dst_cache && dest->dst_cache->dev == dev) {
+ IP_VS_DBG_BUF(3, "Reset dev:%s dest %s:%u ,dest->refcnt=%d\n",
+ dev->name,
+ IP_VS_DBG_ADDR(dest->af, &dest->addr),
+ ntohs(dest->port),
+ atomic_read(&dest->refcnt));
+ ip_vs_dst_reset(dest);
+ }
+ spin_unlock_bh(&dest->dst_lock);
+
+}
+/*
+ * Netdev event receiver
+ * Currently only NETDEV_UNREGISTER is handled, i.e. if we hold a reference to
+ * a device that is "unregister" it must be released.
+ */
+static int ip_vs_dst_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct net *net = dev_net(dev);
+ struct ip_vs_service *svc;
+ struct ip_vs_dest *dest;
+ unsigned int idx;
+
+ if (event != NETDEV_UNREGISTER)
+ return NOTIFY_DONE;
+ IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name);
+ EnterFunction(2);
+ mutex_lock(&__ip_vs_mutex);
+ for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
+ list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
+ if (net_eq(svc->net, net)) {
+ list_for_each_entry(dest, &svc->destinations,
+ n_list) {
+ __ip_vs_dev_reset(dest, dev);
+ }
+ }
+ }
+
+ list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
+ if (net_eq(svc->net, net)) {
+ list_for_each_entry(dest, &svc->destinations,
+ n_list) {
+ __ip_vs_dev_reset(dest, dev);
+ }
+ }
+
+ }
+ }
+
+ list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) {
+ __ip_vs_dev_reset(dest, dev);
+ }
+ mutex_unlock(&__ip_vs_mutex);
+ LeaveFunction(2);
+ return NOTIFY_DONE;
+}
/*
* Zero counters in a service or all services
@@ -3588,6 +3676,10 @@ void __net_init __ip_vs_control_cleanup_sysctl(struct net *net) { }
#endif
+static struct notifier_block ip_vs_dst_notifier = {
+ .notifier_call = ip_vs_dst_event,
+};
+
int __net_init __ip_vs_control_init(struct net *net)
{
int idx;
@@ -3626,7 +3718,7 @@ err:
return -ENOMEM;
}
-static void __net_exit __ip_vs_control_cleanup(struct net *net)
+void __net_exit __ip_vs_control_cleanup(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3639,11 +3731,6 @@ static void __net_exit __ip_vs_control_cleanup(struct net *net)
free_percpu(ipvs->tot_stats.cpustats);
}
-static struct pernet_operations ipvs_control_ops = {
- .init = __ip_vs_control_init,
- .exit = __ip_vs_control_cleanup,
-};
-
int __init ip_vs_control_init(void)
{
int idx;
@@ -3657,33 +3744,32 @@ int __init ip_vs_control_init(void)
INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
}
- ret = register_pernet_subsys(&ipvs_control_ops);
- if (ret) {
- pr_err("cannot register namespace.\n");
- goto err;
- }
-
smp_wmb(); /* Do we really need it now ? */
ret = nf_register_sockopt(&ip_vs_sockopts);
if (ret) {
pr_err("cannot register sockopt.\n");
- goto err_net;
+ goto err_sock;
}
ret = ip_vs_genl_register();
if (ret) {
pr_err("cannot register Generic Netlink interface.\n");
- nf_unregister_sockopt(&ip_vs_sockopts);
- goto err_net;
+ goto err_genl;
}
+ ret = register_netdevice_notifier(&ip_vs_dst_notifier);
+ if (ret < 0)
+ goto err_notf;
+
LeaveFunction(2);
return 0;
-err_net:
- unregister_pernet_subsys(&ipvs_control_ops);
-err:
+err_notf:
+ ip_vs_genl_unregister();
+err_genl:
+ nf_unregister_sockopt(&ip_vs_sockopts);
+err_sock:
return ret;
}
@@ -3691,7 +3777,6 @@ err:
void ip_vs_control_cleanup(void)
{
EnterFunction(2);
- unregister_pernet_subsys(&ipvs_control_ops);
ip_vs_genl_unregister();
nf_unregister_sockopt(&ip_vs_sockopts);
LeaveFunction(2);
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index 8c8766c..508cce9 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -192,7 +192,7 @@ void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
dst->outbps = (e->outbps + 0xF) >> 5;
}
-static int __net_init __ip_vs_estimator_init(struct net *net)
+int __net_init __ip_vs_estimator_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -203,24 +203,16 @@ static int __net_init __ip_vs_estimator_init(struct net *net)
return 0;
}
-static void __net_exit __ip_vs_estimator_exit(struct net *net)
+void __net_exit __ip_vs_estimator_cleanup(struct net *net)
{
del_timer_sync(&net_ipvs(net)->est_timer);
}
-static struct pernet_operations ip_vs_app_ops = {
- .init = __ip_vs_estimator_init,
- .exit = __ip_vs_estimator_exit,
-};
int __init ip_vs_estimator_init(void)
{
- int rv;
-
- rv = register_pernet_subsys(&ip_vs_app_ops);
- return rv;
+ return 0;
}
void ip_vs_estimator_cleanup(void)
{
- unregister_pernet_subsys(&ip_vs_app_ops);
}
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index 17484a4..eb86028 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -316,7 +316,7 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
/*
* per network name-space init
*/
-static int __net_init __ip_vs_protocol_init(struct net *net)
+int __net_init __ip_vs_protocol_init(struct net *net)
{
#ifdef CONFIG_IP_VS_PROTO_TCP
register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp);
@@ -336,7 +336,7 @@ static int __net_init __ip_vs_protocol_init(struct net *net)
return 0;
}
-static void __net_exit __ip_vs_protocol_cleanup(struct net *net)
+void __net_exit __ip_vs_protocol_cleanup(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
struct ip_vs_proto_data *pd;
@@ -349,11 +349,6 @@ static void __net_exit __ip_vs_protocol_cleanup(struct net *net)
}
}
-static struct pernet_operations ipvs_proto_ops = {
- .init = __ip_vs_protocol_init,
- .exit = __ip_vs_protocol_cleanup,
-};
-
int __init ip_vs_protocol_init(void)
{
char protocols[64];
@@ -382,7 +377,6 @@ int __init ip_vs_protocol_init(void)
REGISTER_PROTOCOL(&ip_vs_protocol_esp);
#endif
pr_info("Registered protocols (%s)\n", &protocols[2]);
- return register_pernet_subsys(&ipvs_proto_ops);
return 0;
}
@@ -393,7 +387,6 @@ void ip_vs_protocol_cleanup(void)
struct ip_vs_protocol *pp;
int i;
- unregister_pernet_subsys(&ipvs_proto_ops);
/* unregister all the ipvs protocols */
for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
while ((pp = ip_vs_proto_table[i]) != NULL)
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 0cce953..e292e5b 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1663,7 +1663,7 @@ int stop_sync_thread(struct net *net, int state)
/*
* Initialize data struct for each netns
*/
-static int __net_init __ip_vs_sync_init(struct net *net)
+int __net_init __ip_vs_sync_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -1677,7 +1677,7 @@ static int __net_init __ip_vs_sync_init(struct net *net)
return 0;
}
-static void __ip_vs_sync_cleanup(struct net *net)
+void __ip_vs_sync_cleanup(struct net *net)
{
int retc;
@@ -1690,18 +1690,11 @@ static void __ip_vs_sync_cleanup(struct net *net)
pr_err("Failed to stop Backup Daemon\n");
}
-static struct pernet_operations ipvs_sync_ops = {
- .init = __ip_vs_sync_init,
- .exit = __ip_vs_sync_cleanup,
-};
-
-
int __init ip_vs_sync_init(void)
{
- return register_pernet_device(&ipvs_sync_ops);
+ return 0;
}
void ip_vs_sync_cleanup(void)
{
- unregister_pernet_device(&ipvs_sync_ops);
}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [v4 PATCH 4/6] IPVS: rename of netns init and cleanup functions.
2011-05-01 16:50 [v2 PATCH 0/6] IPVS: init and cleanup Hans Schillstrom
` (2 preceding siblings ...)
2011-05-01 16:50 ` [v4 PATCH 3/6] IPVS: init and cleanup restructuring Hans Schillstrom
@ 2011-05-01 16:50 ` Hans Schillstrom
2011-05-01 16:50 ` [v4 PATCH 5/6] IPVS: remove unused " Hans Schillstrom
` (3 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Hans Schillstrom @ 2011-05-01 16:50 UTC (permalink / raw)
To: ja, horms, ebiederm, lvs-devel, netdev, netfilter-devel
Cc: hans.schillstrom, Hans Schillstrom
Make it more clear what the functions does,
on request by Julian.
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Hans Schillstrom <hans@schillstrom.com>
---
include/net/ip_vs.h | 26 +++++++++++++-------------
net/netfilter/ipvs/ip_vs_app.c | 4 ++--
net/netfilter/ipvs/ip_vs_conn.c | 4 ++--
net/netfilter/ipvs/ip_vs_core.c | 36 ++++++++++++++++++------------------
net/netfilter/ipvs/ip_vs_ctl.c | 20 ++++++++++----------
net/netfilter/ipvs/ip_vs_est.c | 4 ++--
net/netfilter/ipvs/ip_vs_proto.c | 4 ++--
net/netfilter/ipvs/ip_vs_sync.c | 4 ++--
8 files changed, 51 insertions(+), 51 deletions(-)
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 86aefed..da2aea9 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -1093,19 +1093,19 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp)
/*
* IPVS netns init & cleanup functions
*/
-extern int __ip_vs_estimator_init(struct net *net);
-extern int __ip_vs_control_init(struct net *net);
-extern int __ip_vs_protocol_init(struct net *net);
-extern int __ip_vs_app_init(struct net *net);
-extern int __ip_vs_conn_init(struct net *net);
-extern int __ip_vs_sync_init(struct net *net);
-extern void __ip_vs_conn_cleanup(struct net *net);
-extern void __ip_vs_app_cleanup(struct net *net);
-extern void __ip_vs_protocol_cleanup(struct net *net);
-extern void __ip_vs_control_cleanup(struct net *net);
-extern void __ip_vs_estimator_cleanup(struct net *net);
-extern void __ip_vs_sync_cleanup(struct net *net);
-extern void __ip_vs_service_cleanup(struct net *net);
+extern int ip_vs_estimator_net_init(struct net *net);
+extern int ip_vs_control_net_init(struct net *net);
+extern int ip_vs_protocol_net_init(struct net *net);
+extern int ip_vs_app_net_init(struct net *net);
+extern int ip_vs_conn_net_init(struct net *net);
+extern int ip_vs_sync_net_init(struct net *net);
+extern void ip_vs_conn_net_cleanup(struct net *net);
+extern void ip_vs_app_net_cleanup(struct net *net);
+extern void ip_vs_protocol_net_cleanup(struct net *net);
+extern void ip_vs_control_net_cleanup(struct net *net);
+extern void ip_vs_estimator_net_cleanup(struct net *net);
+extern void ip_vs_sync_net_cleanup(struct net *net);
+extern void ip_vs_service_net_cleanup(struct net *net);
/*
* IPVS application functions
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index 51f3af7..81b299d 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -576,7 +576,7 @@ static const struct file_operations ip_vs_app_fops = {
};
#endif
-int __net_init __ip_vs_app_init(struct net *net)
+int __net_init ip_vs_app_net_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -585,7 +585,7 @@ int __net_init __ip_vs_app_init(struct net *net)
return 0;
}
-void __net_exit __ip_vs_app_cleanup(struct net *net)
+void __net_exit ip_vs_app_net_cleanup(struct net *net)
{
proc_net_remove(net, "ip_vs_app");
}
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index d3fd91b..b1e7a0c 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -1247,7 +1247,7 @@ flush_again:
/*
* per netns init and exit
*/
-int __net_init __ip_vs_conn_init(struct net *net)
+int __net_init ip_vs_conn_net_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -1258,7 +1258,7 @@ int __net_init __ip_vs_conn_init(struct net *net)
return 0;
}
-void __net_exit __ip_vs_conn_cleanup(struct net *net)
+void __net_exit ip_vs_conn_net_cleanup(struct net *net)
{
/* flush all the connection entries first */
ip_vs_conn_flush(net);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index b9debc9..4582716 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1911,22 +1911,22 @@ static int __net_init __ip_vs_init(struct net *net)
atomic_inc(&ipvs_netns_cnt);
net->ipvs = ipvs;
- if (__ip_vs_estimator_init(net) < 0)
+ if (ip_vs_estimator_net_init(net) < 0)
goto estimator_fail;
- if (__ip_vs_control_init(net) < 0)
+ if (ip_vs_control_net_init(net) < 0)
goto control_fail;
- if (__ip_vs_protocol_init(net) < 0)
+ if (ip_vs_protocol_net_init(net) < 0)
goto protocol_fail;
- if (__ip_vs_app_init(net) < 0)
+ if (ip_vs_app_net_init(net) < 0)
goto app_fail;
- if (__ip_vs_conn_init(net) < 0)
+ if (ip_vs_conn_net_init(net) < 0)
goto conn_fail;
- if (__ip_vs_sync_init(net) < 0)
+ if (ip_vs_sync_net_init(net) < 0)
goto sync_fail;
printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n",
@@ -1937,27 +1937,27 @@ static int __net_init __ip_vs_init(struct net *net)
*/
sync_fail:
- __ip_vs_conn_cleanup(net);
+ ip_vs_conn_net_cleanup(net);
conn_fail:
- __ip_vs_app_cleanup(net);
+ ip_vs_app_net_cleanup(net);
app_fail:
- __ip_vs_protocol_cleanup(net);
+ ip_vs_protocol_net_cleanup(net);
protocol_fail:
- __ip_vs_control_cleanup(net);
+ ip_vs_control_net_cleanup(net);
control_fail:
- __ip_vs_estimator_cleanup(net);
+ ip_vs_estimator_net_cleanup(net);
estimator_fail:
return -ENOMEM;
}
static void __net_exit __ip_vs_cleanup(struct net *net)
{
- __ip_vs_service_cleanup(net); /* ip_vs_flush() with locks */
- __ip_vs_conn_cleanup(net);
- __ip_vs_app_cleanup(net);
- __ip_vs_protocol_cleanup(net);
- __ip_vs_control_cleanup(net);
- __ip_vs_estimator_cleanup(net);
+ ip_vs_service_net_cleanup(net); /* ip_vs_flush() with locks */
+ ip_vs_conn_net_cleanup(net);
+ ip_vs_app_net_cleanup(net);
+ ip_vs_protocol_net_cleanup(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);
}
@@ -1965,7 +1965,7 @@ static void __net_exit __ip_vs_dev_cleanup(struct net *net)
{
EnterFunction(2);
net_ipvs(net)->enable = 0; /* Disable packet reception */
- __ip_vs_sync_cleanup(net);
+ 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 fe8891f..9074c5d 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1486,7 +1486,7 @@ static int ip_vs_flush(struct net *net)
* Delete service by {netns} in the service table.
* Called by __ip_vs_cleanup()
*/
-void __ip_vs_service_cleanup(struct net *net)
+void ip_vs_service_net_cleanup(struct net *net)
{
EnterFunction(2);
/* Check for "full" addressed entries */
@@ -1665,7 +1665,7 @@ proc_do_sync_mode(ctl_table *table, int write,
/*
* IPVS sysctl table (under the /proc/sys/net/ipv4/vs/)
* Do not change order or insert new entries without
- * align with netns init in __ip_vs_control_init()
+ * align with netns init in ip_vs_control_net_init()
*/
static struct ctl_table vs_vars[] = {
@@ -3601,7 +3601,7 @@ static void ip_vs_genl_unregister(void)
* per netns intit/exit func.
*/
#ifdef CONFIG_SYSCTL
-int __net_init __ip_vs_control_init_sysctl(struct net *net)
+int __net_init ip_vs_control_net_init_sysctl(struct net *net)
{
int idx;
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3660,7 +3660,7 @@ int __net_init __ip_vs_control_init_sysctl(struct net *net)
return 0;
}
-void __net_init __ip_vs_control_cleanup_sysctl(struct net *net)
+void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3671,8 +3671,8 @@ void __net_init __ip_vs_control_cleanup_sysctl(struct net *net)
#else
-int __net_init __ip_vs_control_init_sysctl(struct net *net) { return 0; }
-void __net_init __ip_vs_control_cleanup_sysctl(struct net *net) { }
+int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; }
+void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net) { }
#endif
@@ -3680,7 +3680,7 @@ static struct notifier_block ip_vs_dst_notifier = {
.notifier_call = ip_vs_dst_event,
};
-int __net_init __ip_vs_control_init(struct net *net)
+int __net_init ip_vs_control_net_init(struct net *net)
{
int idx;
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3708,7 +3708,7 @@ int __net_init __ip_vs_control_init(struct net *net)
proc_net_fops_create(net, "ip_vs_stats_percpu", 0,
&ip_vs_stats_percpu_fops);
- if (__ip_vs_control_init_sysctl(net))
+ if (ip_vs_control_net_init_sysctl(net))
goto err;
return 0;
@@ -3718,13 +3718,13 @@ err:
return -ENOMEM;
}
-void __net_exit __ip_vs_control_cleanup(struct net *net)
+void __net_exit ip_vs_control_net_cleanup(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
ip_vs_trash_cleanup(net);
ip_vs_stop_estimator(net, &ipvs->tot_stats);
- __ip_vs_control_cleanup_sysctl(net);
+ ip_vs_control_net_cleanup_sysctl(net);
proc_net_remove(net, "ip_vs_stats_percpu");
proc_net_remove(net, "ip_vs_stats");
proc_net_remove(net, "ip_vs");
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index 508cce9..f5d2a01 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -192,7 +192,7 @@ void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
dst->outbps = (e->outbps + 0xF) >> 5;
}
-int __net_init __ip_vs_estimator_init(struct net *net)
+int __net_init ip_vs_estimator_net_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -203,7 +203,7 @@ int __net_init __ip_vs_estimator_init(struct net *net)
return 0;
}
-void __net_exit __ip_vs_estimator_cleanup(struct net *net)
+void __net_exit ip_vs_estimator_net_cleanup(struct net *net)
{
del_timer_sync(&net_ipvs(net)->est_timer);
}
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index eb86028..52d073c 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -316,7 +316,7 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
/*
* per network name-space init
*/
-int __net_init __ip_vs_protocol_init(struct net *net)
+int __net_init ip_vs_protocol_net_init(struct net *net)
{
#ifdef CONFIG_IP_VS_PROTO_TCP
register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp);
@@ -336,7 +336,7 @@ int __net_init __ip_vs_protocol_init(struct net *net)
return 0;
}
-void __net_exit __ip_vs_protocol_cleanup(struct net *net)
+void __net_exit ip_vs_protocol_net_cleanup(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
struct ip_vs_proto_data *pd;
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index e292e5b..58bfabb 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1663,7 +1663,7 @@ int stop_sync_thread(struct net *net, int state)
/*
* Initialize data struct for each netns
*/
-int __net_init __ip_vs_sync_init(struct net *net)
+int __net_init ip_vs_sync_net_init(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -1677,7 +1677,7 @@ int __net_init __ip_vs_sync_init(struct net *net)
return 0;
}
-void __ip_vs_sync_cleanup(struct net *net)
+void ip_vs_sync_net_cleanup(struct net *net)
{
int retc;
--
1.7.2.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [v4 PATCH 5/6] IPVS: remove unused init and cleanup functions.
2011-05-01 16:50 [v2 PATCH 0/6] IPVS: init and cleanup Hans Schillstrom
` (3 preceding siblings ...)
2011-05-01 16:50 ` [v4 PATCH 4/6] IPVS: rename of netns init and cleanup functions Hans Schillstrom
@ 2011-05-01 16:50 ` Hans Schillstrom
2011-05-01 16:50 ` [v4 PATCH 6/6] IPVS: add debug functions Hans Schillstrom
` (2 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Hans Schillstrom @ 2011-05-01 16:50 UTC (permalink / raw)
To: ja, horms, ebiederm, lvs-devel, netdev, netfilter-devel
Cc: hans.schillstrom, Hans Schillstrom
After restructuring, there is some unused or empty functions
left to be removed.
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Hans Schillstrom <hans@schillstrom.com>
---
include/net/ip_vs.h | 6 ------
net/netfilter/ipvs/ip_vs_app.c | 10 ----------
net/netfilter/ipvs/ip_vs_core.c | 29 ++++-------------------------
net/netfilter/ipvs/ip_vs_est.c | 9 ---------
net/netfilter/ipvs/ip_vs_sync.c | 9 ---------
5 files changed, 4 insertions(+), 59 deletions(-)
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index da2aea9..10417ab 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -1123,8 +1123,6 @@ extern void ip_vs_app_inc_put(struct ip_vs_app *inc);
extern int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb);
extern int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb);
-extern int ip_vs_app_init(void);
-extern void ip_vs_app_cleanup(void);
void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe);
void ip_vs_unbind_pe(struct ip_vs_service *svc);
@@ -1227,15 +1225,11 @@ extern int start_sync_thread(struct net *net, int state, char *mcast_ifn,
__u8 syncid);
extern int stop_sync_thread(struct net *net, int state);
extern void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp);
-extern int ip_vs_sync_init(void);
-extern void ip_vs_sync_cleanup(void);
/*
* IPVS rate estimator prototypes (from ip_vs_est.c)
*/
-extern int ip_vs_estimator_init(void);
-extern void ip_vs_estimator_cleanup(void);
extern void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats);
extern void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats);
extern void ip_vs_zero_estimator(struct ip_vs_stats *stats);
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index 81b299d..5f34cf4 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -589,13 +589,3 @@ void __net_exit ip_vs_app_net_cleanup(struct net *net)
{
proc_net_remove(net, "ip_vs_app");
}
-
-int __init ip_vs_app_init(void)
-{
- return 0;
-}
-
-
-void ip_vs_app_cleanup(void)
-{
-}
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 4582716..91802b1 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1987,36 +1987,23 @@ static int __init ip_vs_init(void)
{
int ret;
- ip_vs_estimator_init();
ret = ip_vs_control_init();
if (ret < 0) {
pr_err("can't setup control.\n");
- goto cleanup_estimator;
+ goto cleanup_out;
}
ip_vs_protocol_init();
- ret = ip_vs_app_init();
- if (ret < 0) {
- pr_err("can't setup application helper.\n");
- goto cleanup_protocol;
- }
-
ret = ip_vs_conn_init();
if (ret < 0) {
pr_err("can't setup connection table.\n");
- goto cleanup_app;
- }
-
- ret = ip_vs_sync_init();
- if (ret < 0) {
- pr_err("can't setup sync data.\n");
- goto cleanup_conn;
+ goto cleanup_protocol;
}
ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */
if (ret < 0)
- goto cleanup_sync;
+ goto cleanup_conn;
ret = register_pernet_device(&ipvs_core_dev_ops);
if (ret < 0)
@@ -2036,17 +2023,12 @@ cleanup_dev:
unregister_pernet_device(&ipvs_core_dev_ops);
cleanup_sub:
unregister_pernet_subsys(&ipvs_core_ops);
-cleanup_sync:
- ip_vs_sync_cleanup();
cleanup_conn:
ip_vs_conn_cleanup();
-cleanup_app:
- ip_vs_app_cleanup();
cleanup_protocol:
ip_vs_protocol_cleanup();
ip_vs_control_cleanup();
-cleanup_estimator:
- ip_vs_estimator_cleanup();
+cleanup_out:
return ret;
}
@@ -2055,12 +2037,9 @@ static void __exit ip_vs_cleanup(void)
nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
unregister_pernet_device(&ipvs_core_dev_ops);
unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
- ip_vs_sync_cleanup();
ip_vs_conn_cleanup();
- ip_vs_app_cleanup();
ip_vs_protocol_cleanup();
ip_vs_control_cleanup();
- ip_vs_estimator_cleanup();
pr_info("ipvs unloaded.\n");
}
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index f5d2a01..0fac601 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -207,12 +207,3 @@ void __net_exit ip_vs_estimator_net_cleanup(struct net *net)
{
del_timer_sync(&net_ipvs(net)->est_timer);
}
-
-int __init ip_vs_estimator_init(void)
-{
- return 0;
-}
-
-void ip_vs_estimator_cleanup(void)
-{
-}
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 58bfabb..7ee7215 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1689,12 +1689,3 @@ void ip_vs_sync_net_cleanup(struct net *net)
if (retc && retc != -ESRCH)
pr_err("Failed to stop Backup Daemon\n");
}
-
-int __init ip_vs_sync_init(void)
-{
- return 0;
-}
-
-void ip_vs_sync_cleanup(void)
-{
-}
--
1.7.2.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [v4 PATCH 6/6] IPVS: add debug functions
2011-05-01 16:50 [v2 PATCH 0/6] IPVS: init and cleanup Hans Schillstrom
` (4 preceding siblings ...)
2011-05-01 16:50 ` [v4 PATCH 5/6] IPVS: remove unused " Hans Schillstrom
@ 2011-05-01 16:50 ` Hans Schillstrom
2011-05-01 17:48 ` [v2 PATCH 0/6] IPVS: init and cleanup Julian Anastasov
2011-06-13 8:18 ` Simon Horman
7 siblings, 0 replies; 10+ messages in thread
From: Hans Schillstrom @ 2011-05-01 16:50 UTC (permalink / raw)
To: ja, horms, ebiederm, lvs-devel, netdev, netfilter-devel
Cc: hans.schillstrom, Hans Schillstrom
Optional patch, but it is nice to have.
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
Signed-off-by: Hans Schillstrom <hans@schillstrom.com>
---
net/netfilter/ipvs/ip_vs_ctl.c | 13 ++++++++++++-
1 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 9074c5d..a1fab5b 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -351,8 +351,11 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
svc->flags &= ~IP_VS_SVC_F_HASHED;
atomic_dec(&svc->refcnt);
/* No more services, no need for input */
- if (atomic_read(&svc->refcnt) == 0)
+ if (atomic_read(&svc->refcnt) == 0) {
net_ipvs(svc->net)->enable = 0;
+ IP_VS_DBG(2, "Last service removed in net(%d) input disabled\n",
+ net_ipvs(svc->net)->gen);
+ }
return 1;
}
@@ -1222,6 +1225,10 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
write_unlock_bh(&__ip_vs_svc_lock);
*svc_p = svc;
+ if (!ipvs->enable)
+ pr_info("netns(%d) enabled, first service added\n",
+ ipvs->gen);
+
/* Now there is a service - full throttle */
ipvs->enable = 1;
return 0;
@@ -3685,6 +3692,7 @@ int __net_init ip_vs_control_net_init(struct net *net)
int idx;
struct netns_ipvs *ipvs = net_ipvs(net);
+ EnterFunction(2);
ipvs->rs_lock = __RW_LOCK_UNLOCKED(ipvs->rs_lock);
/* Initialize rs_table */
@@ -3711,6 +3719,7 @@ int __net_init ip_vs_control_net_init(struct net *net)
if (ip_vs_control_net_init_sysctl(net))
goto err;
+ LeaveFunction(2);
return 0;
err:
@@ -3722,6 +3731,7 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
+ EnterFunction(2);
ip_vs_trash_cleanup(net);
ip_vs_stop_estimator(net, &ipvs->tot_stats);
ip_vs_control_net_cleanup_sysctl(net);
@@ -3729,6 +3739,7 @@ void __net_exit ip_vs_control_net_cleanup(struct net *net)
proc_net_remove(net, "ip_vs_stats");
proc_net_remove(net, "ip_vs");
free_percpu(ipvs->tot_stats.cpustats);
+ LeaveFunction(2);
}
int __init ip_vs_control_init(void)
--
1.7.2.3
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [v2 PATCH 0/6] IPVS: init and cleanup.
2011-05-01 16:50 [v2 PATCH 0/6] IPVS: init and cleanup Hans Schillstrom
` (5 preceding siblings ...)
2011-05-01 16:50 ` [v4 PATCH 6/6] IPVS: add debug functions Hans Schillstrom
@ 2011-05-01 17:48 ` Julian Anastasov
2011-06-13 8:18 ` Simon Horman
7 siblings, 0 replies; 10+ messages in thread
From: Julian Anastasov @ 2011-05-01 17:48 UTC (permalink / raw)
To: Hans Schillstrom
Cc: horms, ebiederm, lvs-devel, netdev, netfilter-devel,
hans.schillstrom
Hello,
On Sun, 1 May 2011, Hans Schillstrom wrote:
> This patch series handles exit from a network name space.
>
> REVISION
>
> This is version 4
>
> OVERVIEW
> Basically there was three faults in the netns implementation.
> - Kernel threads hold devices and preventing an exit.
> - dst cache holds references to devices.
> - Services was not always released.
>
> Patch 1 & 3 contains the functionality
> 4 renames funcctions
> 5 removes empty functions
> 6 Debuging.
>
> IMPLEMENTATION
> - Avoid to increment the usage counter for kernel threads.
> this is done in the first patch.
> - Patch 3 tries to restore the cleanup order.
> Add NETDEV_UNREGISTER notification for dst_reset
> (eleased version could not handle unregistration of netdevices.)
>
> Comments from Eric, Julian and Simon implmented.
>
> Revision 3
> Residies in patch 3
> Throttle renamed to enable.
> Comments from Julian implemented
> Check enable in ip_vs_in, ip_vs_out and ip_vs_forward_icmp*
> Remove in ip_vs_in_icmp*.
> ip_vs_svc_reset() moved into ip_vs_dst_event().
> ip_vs_service_cleanup() uses ip_vs_flush and mutex lock.
> ip_vs_unlink_service_nolock() added.
>
> Revision 4
> ip_vs_unlink_service_nolock() removed.
> ip_vs_flush() reverted.
> Return code check changed in stop thread.
Not sure about patch 1 but patches 2-6 in v4 look
good to me. Thanks!
Acked-by: Julian Anastasov <ja@ssi.bg>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [v2 PATCH 0/6] IPVS: init and cleanup.
2011-05-01 16:50 [v2 PATCH 0/6] IPVS: init and cleanup Hans Schillstrom
` (6 preceding siblings ...)
2011-05-01 17:48 ` [v2 PATCH 0/6] IPVS: init and cleanup Julian Anastasov
@ 2011-06-13 8:18 ` Simon Horman
7 siblings, 0 replies; 10+ messages in thread
From: Simon Horman @ 2011-06-13 8:18 UTC (permalink / raw)
To: Hans Schillstrom
Cc: ja, ebiederm, lvs-devel, netdev, netfilter-devel,
hans.schillstrom
Hi Hans,
this series consisted of the following patches:
[v4 PATCH 1/6] IPVS: Change of socket usage to enable name space exit.
[v4 PATCH 2/6] IPVS: labels at pos 0
[v4 PATCH 3/6] IPVS: init and cleanup restructuring.
[v4 PATCH 4/6] IPVS: rename of netns init and cleanup functions.
[v4 PATCH 5/6] IPVS: remove unused init and cleanup functions.
[v4 PATCH 6/6] IPVS: add debug functions
Variants of 1/6 and 3/6 were included in 2.6.39.
I have applied 4/6 to ipvs-next-2.6 [1]
The remaining patches no longer apply cleanly,
could you send fresh versions?
[1] git://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs-next-2.6.git
^ permalink raw reply [flat|nested] 10+ messages in thread