[rds-devel] [PATCH 11/19] Add infrastructure for per network namespace RDS sysctl. - Introduce a new struct rds_sysctl_option to hold those global sysctl options. - Make rds_sysctl_init()/exit() aware of struct net. - Move rds_sysctl_init()/exit() to per netns init/exit.

Jie Liu jeff.liu at oracle.com
Sun Oct 7 05:18:03 PDT 2012


Signed-off-by: Jie Liu <jeff.liu at oracle.com>
---
 include/net/netns/rds.h |   18 ++++++++++++
 net/rds/af_rds.c        |   25 ++++++++++------
 net/rds/rds.h           |    4 +-
 net/rds/sysctl.c        |   71 +++++++++++++++++++++++++++++++++++------------
 4 files changed, 89 insertions(+), 29 deletions(-)

diff --git a/include/net/netns/rds.h b/include/net/netns/rds.h
index 76afd59..e47bfe6 100644
--- a/include/net/netns/rds.h
+++ b/include/net/netns/rds.h
@@ -1,6 +1,18 @@
 #ifndef __NETNS_RDS_H
 #define __NETNS_RDS_H
 
+struct ctl_table_header;
+
+struct rds_sysctl_option {
+	unsigned long   reconnect_min;
+	unsigned long   reconnect_max;
+	unsigned long   reconnect_min_jiffies;
+	unsigned long   reconnect_max_jiffies;
+	unsigned int    max_unacked_packets;
+	unsigned int    max_unacked_bytes;
+	unsigned int    ping_enable;
+};
+
 struct netns_rds {
 	/* connection count */
 	unsigned long rds_conn_count;
@@ -22,6 +34,12 @@ struct netns_rds {
 
 	/* global statistics */
 	struct rds_statistics __percpu *rds_stats;
+
+	struct rds_sysctl_option rds_sysctl;
+
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header *rds_sysctl_hdr;
+#endif
 };
 
 #endif
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c
index 41e1d95..8a6c883 100644
--- a/net/rds/af_rds.c
+++ b/net/rds/af_rds.c
@@ -544,12 +544,25 @@ static int __net_init rds_pernet_init(struct net *net)
 	spin_lock_init(&net->rds.rds_sock_lock);
 	net->rds.rds_sock_count = 0;
 
+	ret = rds_sysctl_init(net);
+	if (ret)
+		goto out;
+
 	net->rds.rds_stats = alloc_percpu(struct rds_statistics);
 	if (!net->rds.rds_stats)
-		goto out;
+		goto out_sysctl;
 
 	ret = rds_cong_init(net);
+	if (ret)
+		goto out_stats;
 
+	goto out;
+
+out_stats:
+	free_percpu(net->rds.rds_stats);
+	net->rds.rds_stats = NULL;
+out_sysctl:
+	rds_sysctl_exit(net);
 out:
 	return ret;
 }
@@ -559,6 +572,7 @@ static void __net_exit rds_pernet_exit(struct net *net)
 	rds_cong_exit(net);
 	free_percpu(net->rds.rds_stats);
 	net->rds.rds_stats = NULL;
+	rds_sysctl_exit(net);
 }
 
 static struct pernet_operations __net_initdata rds_net_ops = {
@@ -582,7 +596,6 @@ static void rds_exit(void)
 	proto_unregister(&rds_proto);
 	rds_loop_exit();
 	rds_conn_exit();
-	rds_sysctl_exit();
 	rds_net_exit();
 	rds_threads_exit();
 	rds_stats_exit();
@@ -608,13 +621,9 @@ static int rds_init(void)
 	if (ret)
 		goto out_conn;
 
-	ret = rds_sysctl_init();
-	if (ret)
-		goto out_threads;
-
 	ret = rds_net_init();
 	if (ret)
-		goto out_sysctl;
+		goto out_threads;
 
 	ret = rds_stats_init();
 	if (ret)
@@ -639,8 +648,6 @@ out_stats:
 	rds_stats_exit();
 out_net:
 	rds_net_exit();
-out_sysctl:
-	rds_sysctl_exit();
 out_threads:
 	rds_threads_exit();
 out_conn:
diff --git a/net/rds/rds.h b/net/rds/rds.h
index fdf8103..85e2c44 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -790,8 +790,8 @@ void rds_stats_info_copy(struct rds_info_iterator *iter,
 			 size_t nr);
 
 /* sysctl.c */
-int rds_sysctl_init(void);
-void rds_sysctl_exit(void);
+int rds_sysctl_init(struct net *net);
+void rds_sysctl_exit(struct net *net);
 extern unsigned long rds_sysctl_sndbuf_min;
 extern unsigned long rds_sysctl_sndbuf_default;
 extern unsigned long rds_sysctl_sndbuf_max;
diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c
index 907214b..5c6e831 100644
--- a/net/rds/sysctl.c
+++ b/net/rds/sysctl.c
@@ -36,23 +36,21 @@
 
 #include "rds.h"
 
-static struct ctl_table_header *rds_sysctl_reg_table;
-
 static unsigned long rds_sysctl_reconnect_min = 1;
 static unsigned long rds_sysctl_reconnect_max = ~0UL;
 
 unsigned long rds_sysctl_reconnect_min_jiffies;
 unsigned long rds_sysctl_reconnect_max_jiffies = HZ;
 
-unsigned int  rds_sysctl_max_unacked_packets = 8;
-unsigned int  rds_sysctl_max_unacked_bytes = (16 << 20);
+unsigned int rds_sysctl_max_unacked_packets = 8;
+unsigned int rds_sysctl_max_unacked_bytes = (16 << 20);
 
 unsigned int rds_sysctl_ping_enable = 1;
 
 static ctl_table rds_sysctl_rds_table[] = {
 	{
 		.procname       = "reconnect_min_delay_ms",
-		.data		= &rds_sysctl_reconnect_min_jiffies,
+		.data		= &init_net.rds.rds_sysctl.reconnect_min_jiffies,
 		.maxlen         = sizeof(unsigned long),
 		.mode           = 0644,
 		.proc_handler   = proc_doulongvec_ms_jiffies_minmax,
@@ -61,7 +59,7 @@ static ctl_table rds_sysctl_rds_table[] = {
 	},
 	{
 		.procname       = "reconnect_max_delay_ms",
-		.data		= &rds_sysctl_reconnect_max_jiffies,
+		.data		= &init_net.rds.rds_sysctl.reconnect_max_jiffies,
 		.maxlen         = sizeof(unsigned long),
 		.mode           = 0644,
 		.proc_handler   = proc_doulongvec_ms_jiffies_minmax,
@@ -70,21 +68,21 @@ static ctl_table rds_sysctl_rds_table[] = {
 	},
 	{
 		.procname	= "max_unacked_packets",
-		.data		= &rds_sysctl_max_unacked_packets,
+		.data		= &init_net.rds.rds_sysctl.max_unacked_packets,
 		.maxlen         = sizeof(unsigned long),
 		.mode           = 0644,
 		.proc_handler   = proc_dointvec,
 	},
 	{
 		.procname	= "max_unacked_bytes",
-		.data		= &rds_sysctl_max_unacked_bytes,
+		.data		= &init_net.rds.rds_sysctl.max_unacked_bytes,
 		.maxlen         = sizeof(unsigned long),
 		.mode           = 0644,
 		.proc_handler   = proc_dointvec,
 	},
 	{
 		.procname	= "ping_enable",
-		.data		= &rds_sysctl_ping_enable,
+		.data		= &init_net.rds.rds_sysctl.ping_enable,
 		.maxlen         = sizeof(int),
 		.mode           = 0644,
 		.proc_handler   = proc_dointvec,
@@ -92,19 +90,56 @@ static ctl_table rds_sysctl_rds_table[] = {
 	{ }
 };
 
-void rds_sysctl_exit(void)
+int rds_sysctl_init(struct net *net)
 {
-	if (rds_sysctl_reg_table)
-		unregister_net_sysctl_table(rds_sysctl_reg_table);
-}
+	struct rds_sysctl_option *rds_sysctl;
+	struct ctl_table *table;
 
-int rds_sysctl_init(void)
-{
 	rds_sysctl_reconnect_min = msecs_to_jiffies(1);
 	rds_sysctl_reconnect_min_jiffies = rds_sysctl_reconnect_min;
 
-	rds_sysctl_reg_table = register_net_sysctl(&init_net,"net/rds", rds_sysctl_rds_table);
-	if (!rds_sysctl_reg_table)
-		return -ENOMEM;
+	rds_sysctl = &net->rds.rds_sysctl;
+	rds_sysctl->reconnect_min = rds_sysctl_reconnect_min;
+	rds_sysctl->reconnect_max = rds_sysctl_reconnect_max;
+	rds_sysctl->reconnect_min_jiffies = rds_sysctl_reconnect_min_jiffies;
+	rds_sysctl->reconnect_max_jiffies = rds_sysctl_reconnect_max_jiffies;
+	rds_sysctl->max_unacked_packets = rds_sysctl_max_unacked_packets;
+	rds_sysctl->max_unacked_bytes = rds_sysctl_max_unacked_bytes;
+	rds_sysctl->ping_enable = rds_sysctl_ping_enable;
+
+	table = rds_sysctl_rds_table;
+	if (!net_eq(&init_net, net)) {
+		table = kmemdup(rds_sysctl_rds_table,
+				sizeof(rds_sysctl_rds_table), GFP_KERNEL);
+		if (!table)
+			goto out_alloc;
+
+		table[0].data = &rds_sysctl->reconnect_min_jiffies;
+		table[1].data = &rds_sysctl->reconnect_max_jiffies;
+		table[2].data = &rds_sysctl->max_unacked_packets;
+		table[3].data = &rds_sysctl->max_unacked_bytes;
+		table[4].data = &rds_sysctl->ping_enable;
+	}
+
+	net->rds.rds_sysctl_hdr = register_net_sysctl(net, "net/rds", table);
+	if (!net->rds.rds_sysctl_hdr)
+		goto out_sysctl_reg;
+
 	return 0;
+
+out_sysctl_reg:
+	if (!net_eq(&init_net, net))
+		kfree(table);
+out_alloc:
+	return -ENOMEM;
+}
+
+void rds_sysctl_exit(struct net *net)
+{
+	struct ctl_table *table;
+
+        table = net->rds.rds_sysctl_hdr->ctl_table_arg;
+	unregister_net_sysctl_table(net->rds.rds_sysctl_hdr);
+	if (!net_eq(&init_net, net))
+		kfree(table);
 }
-- 
1.7.4.1




More information about the rds-devel mailing list