aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2007-10-08 23:38:39 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:54:58 -0400
commit4665079cbb2a3e17de82f2ab2940b9f97f37d65e (patch)
tree8e51e9b9e6155eaeccf28783620a07b20a067d8d
parentd62a38d1ab350f787e4941e42a3d3e97971e38f5 (diff)
[NETNS]: Move some code into __init section when CONFIG_NET_NS=n
With the net namespaces many code leaved the __init section, thus making the kernel occupy more memory than it did before. Since we have a config option that prohibits the namespace creation, the functions that initialize/finalize some netns stuff are simply not needed and can be freed after the boot. Currently, this is almost not noticeable, since few calls are no longer in __init, but when the namespaces will be merged it will be possible to free more code. I propose to use the __net_init, __net_exit and __net_initdata "attributes" for functions/variables that are not used if the CONFIG_NET_NS is not set to save more space in memory. The exiting functions cannot just reside in the __exit section, as noticed by David, since the init section will have references on it and the compilation will fail due to modpost checks. These references can exist, since the init namespace never dies and the exit callbacks are never called. So I introduce the __exit_refok attribute just like it is already done with the __init_refok. Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/loopback.c6
-rw-r--r--fs/proc/proc_net.c8
-rw-r--r--include/linux/init.h1
-rw-r--r--include/net/net_namespace.h9
-rw-r--r--net/core/dev.c16
-rw-r--r--net/core/dev_mcast.c6
-rw-r--r--net/netlink/af_netlink.c6
-rw-r--r--scripts/mod/modpost.c1
8 files changed, 32 insertions, 21 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index d6997aec45dd..be25aa33971c 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -250,7 +250,7 @@ static void loopback_setup(struct net_device *dev)
250} 250}
251 251
252/* Setup and register the loopback device. */ 252/* Setup and register the loopback device. */
253static int loopback_net_init(struct net *net) 253static __net_init int loopback_net_init(struct net *net)
254{ 254{
255 struct net_device *dev; 255 struct net_device *dev;
256 int err; 256 int err;
@@ -278,14 +278,14 @@ out_free_netdev:
278 goto out; 278 goto out;
279} 279}
280 280
281static void loopback_net_exit(struct net *net) 281static __net_exit void loopback_net_exit(struct net *net)
282{ 282{
283 struct net_device *dev = net->loopback_dev; 283 struct net_device *dev = net->loopback_dev;
284 284
285 unregister_netdev(dev); 285 unregister_netdev(dev);
286} 286}
287 287
288static struct pernet_operations loopback_net_ops = { 288static struct pernet_operations __net_initdata loopback_net_ops = {
289 .init = loopback_net_init, 289 .init = loopback_net_init,
290 .exit = loopback_net_exit, 290 .exit = loopback_net_exit,
291}; 291};
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 85cc8e8bb862..2e91fb756e9a 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -140,7 +140,7 @@ static struct inode_operations proc_net_dir_inode_operations = {
140 .setattr = proc_net_setattr, 140 .setattr = proc_net_setattr,
141}; 141};
142 142
143static int proc_net_ns_init(struct net *net) 143static __net_init int proc_net_ns_init(struct net *net)
144{ 144{
145 struct proc_dir_entry *root, *netd, *net_statd; 145 struct proc_dir_entry *root, *netd, *net_statd;
146 int err; 146 int err;
@@ -178,19 +178,19 @@ free_root:
178 goto out; 178 goto out;
179} 179}
180 180
181static void proc_net_ns_exit(struct net *net) 181static __net_exit void proc_net_ns_exit(struct net *net)
182{ 182{
183 remove_proc_entry("stat", net->proc_net); 183 remove_proc_entry("stat", net->proc_net);
184 remove_proc_entry("net", net->proc_net_root); 184 remove_proc_entry("net", net->proc_net_root);
185 kfree(net->proc_net_root); 185 kfree(net->proc_net_root);
186} 186}
187 187
188struct pernet_operations proc_net_ns_ops = { 188struct pernet_operations __net_initdata proc_net_ns_ops = {
189 .init = proc_net_ns_init, 189 .init = proc_net_ns_init,
190 .exit = proc_net_ns_exit, 190 .exit = proc_net_ns_exit,
191}; 191};
192 192
193int proc_net_init(void) 193int __init proc_net_init(void)
194{ 194{
195 proc_net_shadow = proc_mkdir("net", NULL); 195 proc_net_shadow = proc_mkdir("net", NULL);
196 proc_net_shadow->proc_iops = &proc_net_dir_inode_operations; 196 proc_net_shadow->proc_iops = &proc_net_dir_inode_operations;
diff --git a/include/linux/init.h b/include/linux/init.h
index 74b1f43bf982..f8d9d0b5cffc 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -57,6 +57,7 @@
57 * The markers follow same syntax rules as __init / __initdata. */ 57 * The markers follow same syntax rules as __init / __initdata. */
58#define __init_refok noinline __attribute__ ((__section__ (".text.init.refok"))) 58#define __init_refok noinline __attribute__ ((__section__ (".text.init.refok")))
59#define __initdata_refok __attribute__ ((__section__ (".data.init.refok"))) 59#define __initdata_refok __attribute__ ((__section__ (".data.init.refok")))
60#define __exit_refok noinline __attribute__ ((__section__ (".exit.text.refok")))
60 61
61#ifdef MODULE 62#ifdef MODULE
62#define __exit __attribute__ ((__section__(".exit.text"))) __cold 63#define __exit __attribute__ ((__section__(".exit.text"))) __cold
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 934c840b5941..93aa87d32804 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -99,6 +99,15 @@ static inline void release_net(struct net *net)
99#define for_each_net(VAR) \ 99#define for_each_net(VAR) \
100 list_for_each_entry(VAR, &net_namespace_list, list) 100 list_for_each_entry(VAR, &net_namespace_list, list)
101 101
102#ifdef CONFIG_NET_NS
103#define __net_init
104#define __net_exit
105#define __net_initdata
106#else
107#define __net_init __init
108#define __net_exit __exit_refok
109#define __net_initdata __initdata
110#endif
102 111
103struct pernet_operations { 112struct pernet_operations {
104 struct list_head list; 113 struct list_head list;
diff --git a/net/core/dev.c b/net/core/dev.c
index 1aa07047826e..e7e728aea9f3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2611,7 +2611,7 @@ static const struct file_operations ptype_seq_fops = {
2611}; 2611};
2612 2612
2613 2613
2614static int dev_proc_net_init(struct net *net) 2614static int __net_init dev_proc_net_init(struct net *net)
2615{ 2615{
2616 int rc = -ENOMEM; 2616 int rc = -ENOMEM;
2617 2617
@@ -2636,7 +2636,7 @@ out_dev:
2636 goto out; 2636 goto out;
2637} 2637}
2638 2638
2639static void dev_proc_net_exit(struct net *net) 2639static void __net_exit dev_proc_net_exit(struct net *net)
2640{ 2640{
2641 wext_proc_exit(net); 2641 wext_proc_exit(net);
2642 2642
@@ -2645,7 +2645,7 @@ static void dev_proc_net_exit(struct net *net)
2645 proc_net_remove(net, "dev"); 2645 proc_net_remove(net, "dev");
2646} 2646}
2647 2647
2648static struct pernet_operations dev_proc_ops = { 2648static struct pernet_operations __net_initdata dev_proc_ops = {
2649 .init = dev_proc_net_init, 2649 .init = dev_proc_net_init,
2650 .exit = dev_proc_net_exit, 2650 .exit = dev_proc_net_exit,
2651}; 2651};
@@ -4278,7 +4278,7 @@ static struct hlist_head *netdev_create_hash(void)
4278} 4278}
4279 4279
4280/* Initialize per network namespace state */ 4280/* Initialize per network namespace state */
4281static int netdev_init(struct net *net) 4281static int __net_init netdev_init(struct net *net)
4282{ 4282{
4283 INIT_LIST_HEAD(&net->dev_base_head); 4283 INIT_LIST_HEAD(&net->dev_base_head);
4284 rwlock_init(&dev_base_lock); 4284 rwlock_init(&dev_base_lock);
@@ -4299,18 +4299,18 @@ err_name:
4299 return -ENOMEM; 4299 return -ENOMEM;
4300} 4300}
4301 4301
4302static void netdev_exit(struct net *net) 4302static void __net_exit netdev_exit(struct net *net)
4303{ 4303{
4304 kfree(net->dev_name_head); 4304 kfree(net->dev_name_head);
4305 kfree(net->dev_index_head); 4305 kfree(net->dev_index_head);
4306} 4306}
4307 4307
4308static struct pernet_operations netdev_net_ops = { 4308static struct pernet_operations __net_initdata netdev_net_ops = {
4309 .init = netdev_init, 4309 .init = netdev_init,
4310 .exit = netdev_exit, 4310 .exit = netdev_exit,
4311}; 4311};
4312 4312
4313static void default_device_exit(struct net *net) 4313static void __net_exit default_device_exit(struct net *net)
4314{ 4314{
4315 struct net_device *dev, *next; 4315 struct net_device *dev, *next;
4316 /* 4316 /*
@@ -4336,7 +4336,7 @@ static void default_device_exit(struct net *net)
4336 rtnl_unlock(); 4336 rtnl_unlock();
4337} 4337}
4338 4338
4339static struct pernet_operations default_device_ops = { 4339static struct pernet_operations __net_initdata default_device_ops = {
4340 .exit = default_device_exit, 4340 .exit = default_device_exit,
4341}; 4341};
4342 4342
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 896b0ca5aed7..15241cf48af8 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -273,19 +273,19 @@ static const struct file_operations dev_mc_seq_fops = {
273 273
274#endif 274#endif
275 275
276static int dev_mc_net_init(struct net *net) 276static int __net_init dev_mc_net_init(struct net *net)
277{ 277{
278 if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops)) 278 if (!proc_net_fops_create(net, "dev_mcast", 0, &dev_mc_seq_fops))
279 return -ENOMEM; 279 return -ENOMEM;
280 return 0; 280 return 0;
281} 281}
282 282
283static void dev_mc_net_exit(struct net *net) 283static void __net_exit dev_mc_net_exit(struct net *net)
284{ 284{
285 proc_net_remove(net, "dev_mcast"); 285 proc_net_remove(net, "dev_mcast");
286} 286}
287 287
288static struct pernet_operations dev_mc_net_ops = { 288static struct pernet_operations __net_initdata dev_mc_net_ops = {
289 .init = dev_mc_net_init, 289 .init = dev_mc_net_init,
290 .exit = dev_mc_net_exit, 290 .exit = dev_mc_net_exit,
291}; 291};
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 46eb5ea1fbd7..3ef32825da71 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1924,7 +1924,7 @@ static struct net_proto_family netlink_family_ops = {
1924 .owner = THIS_MODULE, /* for consistency 8) */ 1924 .owner = THIS_MODULE, /* for consistency 8) */
1925}; 1925};
1926 1926
1927static int netlink_net_init(struct net *net) 1927static int __net_init netlink_net_init(struct net *net)
1928{ 1928{
1929#ifdef CONFIG_PROC_FS 1929#ifdef CONFIG_PROC_FS
1930 if (!proc_net_fops_create(net, "netlink", 0, &netlink_seq_fops)) 1930 if (!proc_net_fops_create(net, "netlink", 0, &netlink_seq_fops))
@@ -1933,14 +1933,14 @@ static int netlink_net_init(struct net *net)
1933 return 0; 1933 return 0;
1934} 1934}
1935 1935
1936static void netlink_net_exit(struct net *net) 1936static void __net_exit netlink_net_exit(struct net *net)
1937{ 1937{
1938#ifdef CONFIG_PROC_FS 1938#ifdef CONFIG_PROC_FS
1939 proc_net_remove(net, "netlink"); 1939 proc_net_remove(net, "netlink");
1940#endif 1940#endif
1941} 1941}
1942 1942
1943static struct pernet_operations netlink_net_ops = { 1943static struct pernet_operations __net_initdata netlink_net_ops = {
1944 .init = netlink_net_init, 1944 .init = netlink_net_init,
1945 .exit = netlink_net_exit, 1945 .exit = netlink_net_exit,
1946}; 1946};
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 6c145d6e89de..0a4051fbd34e 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -709,6 +709,7 @@ static int secref_whitelist(const char *modname, const char *tosec,
709 709
710 /* Check for pattern 0 */ 710 /* Check for pattern 0 */
711 if ((strncmp(fromsec, ".text.init.refok", strlen(".text.init.refok")) == 0) || 711 if ((strncmp(fromsec, ".text.init.refok", strlen(".text.init.refok")) == 0) ||
712 (strncmp(fromsec, ".exit.text.refok", strlen(".exit.text.refok")) == 0) ||
712 (strncmp(fromsec, ".data.init.refok", strlen(".data.init.refok")) == 0)) 713 (strncmp(fromsec, ".data.init.refok", strlen(".data.init.refok")) == 0))
713 return 1; 714 return 1;
714 715