diff options
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/sysctl_net_core.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index e322713e590a..57a7eadb8551 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c | |||
@@ -151,18 +151,58 @@ static struct ctl_table net_core_table[] = { | |||
151 | { .ctl_name = 0 } | 151 | { .ctl_name = 0 } |
152 | }; | 152 | }; |
153 | 153 | ||
154 | static __initdata struct ctl_path net_core_path[] = { | 154 | static __net_initdata struct ctl_path net_core_path[] = { |
155 | { .procname = "net", .ctl_name = CTL_NET, }, | 155 | { .procname = "net", .ctl_name = CTL_NET, }, |
156 | { .procname = "core", .ctl_name = NET_CORE, }, | 156 | { .procname = "core", .ctl_name = NET_CORE, }, |
157 | { }, | 157 | { }, |
158 | }; | 158 | }; |
159 | 159 | ||
160 | static __init int sysctl_core_init(void) | 160 | static __net_init int sysctl_core_net_init(struct net *net) |
161 | { | 161 | { |
162 | struct ctl_table_header *hdr; | 162 | struct ctl_table *tbl, *tmp; |
163 | |||
164 | tbl = net_core_table; | ||
165 | if (net != &init_net) { | ||
166 | tbl = kmemdup(tbl, sizeof(net_core_table), GFP_KERNEL); | ||
167 | if (tbl == NULL) | ||
168 | goto err_dup; | ||
169 | |||
170 | for (tmp = tbl; tmp->procname; tmp++) | ||
171 | tmp->mode &= ~0222; | ||
172 | } | ||
173 | |||
174 | net->sysctl_core_hdr = register_net_sysctl_table(net, | ||
175 | net_core_path, tbl); | ||
176 | if (net->sysctl_core_hdr == NULL) | ||
177 | goto err_reg; | ||
163 | 178 | ||
164 | hdr = register_sysctl_paths(net_core_path, net_core_table); | 179 | return 0; |
165 | return hdr == NULL ? -ENOMEM : 0; | 180 | |
181 | err_reg: | ||
182 | if (tbl != net_core_table) | ||
183 | kfree(tbl); | ||
184 | err_dup: | ||
185 | return -ENOMEM; | ||
186 | } | ||
187 | |||
188 | static __net_exit void sysctl_core_net_exit(struct net *net) | ||
189 | { | ||
190 | struct ctl_table *tbl; | ||
191 | |||
192 | tbl = net->sysctl_core_hdr->ctl_table_arg; | ||
193 | unregister_net_sysctl_table(net->sysctl_core_hdr); | ||
194 | BUG_ON(tbl == net_core_table); | ||
195 | kfree(tbl); | ||
196 | } | ||
197 | |||
198 | static __net_initdata struct pernet_operations sysctl_core_ops = { | ||
199 | .init = sysctl_core_net_init, | ||
200 | .exit = sysctl_core_net_exit, | ||
201 | }; | ||
202 | |||
203 | static __init int sysctl_core_init(void) | ||
204 | { | ||
205 | return register_pernet_subsys(&sysctl_core_ops); | ||
166 | } | 206 | } |
167 | 207 | ||
168 | __initcall(sysctl_core_init); | 208 | __initcall(sysctl_core_init); |