aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-02-24 06:50:29 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-24 06:50:29 -0500
commite70049b9e74267dd47e1ffa62302073487afcb48 (patch)
tree2cd000c0751ef31c9044b020d63f278cdf4f332d /net/core
parentd18921a0e319ab512f8186b1b1142c7b8634c779 (diff)
parentf7e603ad8f78cd3b59e33fa72707da0cbabdf699 (diff)
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Diffstat (limited to 'net/core')
-rw-r--r--net/core/net_namespace.c86
-rw-r--r--net/core/skbuff.c8
-rw-r--r--net/core/sock.c3
3 files changed, 56 insertions, 41 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 516c7b154327..e3bebd36f053 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -32,24 +32,14 @@ static __net_init int setup_net(struct net *net)
32{ 32{
33 /* Must be called with net_mutex held */ 33 /* Must be called with net_mutex held */
34 struct pernet_operations *ops; 34 struct pernet_operations *ops;
35 int error; 35 int error = 0;
36 struct net_generic *ng;
37 36
38 atomic_set(&net->count, 1); 37 atomic_set(&net->count, 1);
38
39#ifdef NETNS_REFCNT_DEBUG 39#ifdef NETNS_REFCNT_DEBUG
40 atomic_set(&net->use_count, 0); 40 atomic_set(&net->use_count, 0);
41#endif 41#endif
42 42
43 error = -ENOMEM;
44 ng = kzalloc(sizeof(struct net_generic) +
45 INITIAL_NET_GEN_PTRS * sizeof(void *), GFP_KERNEL);
46 if (ng == NULL)
47 goto out;
48
49 ng->len = INITIAL_NET_GEN_PTRS;
50 rcu_assign_pointer(net->gen, ng);
51
52 error = 0;
53 list_for_each_entry(ops, &pernet_list, list) { 43 list_for_each_entry(ops, &pernet_list, list) {
54 if (ops->init) { 44 if (ops->init) {
55 error = ops->init(net); 45 error = ops->init(net);
@@ -70,24 +60,50 @@ out_undo:
70 } 60 }
71 61
72 rcu_barrier(); 62 rcu_barrier();
73 kfree(ng);
74 goto out; 63 goto out;
75} 64}
76 65
66static struct net_generic *net_alloc_generic(void)
67{
68 struct net_generic *ng;
69 size_t generic_size = sizeof(struct net_generic) +
70 INITIAL_NET_GEN_PTRS * sizeof(void *);
71
72 ng = kzalloc(generic_size, GFP_KERNEL);
73 if (ng)
74 ng->len = INITIAL_NET_GEN_PTRS;
75
76 return ng;
77}
78
77#ifdef CONFIG_NET_NS 79#ifdef CONFIG_NET_NS
78static struct kmem_cache *net_cachep; 80static struct kmem_cache *net_cachep;
79static struct workqueue_struct *netns_wq; 81static struct workqueue_struct *netns_wq;
80 82
81static struct net *net_alloc(void) 83static struct net *net_alloc(void)
82{ 84{
83 return kmem_cache_zalloc(net_cachep, GFP_KERNEL); 85 struct net *net = NULL;
86 struct net_generic *ng;
87
88 ng = net_alloc_generic();
89 if (!ng)
90 goto out;
91
92 net = kmem_cache_zalloc(net_cachep, GFP_KERNEL);
93 if (!net)
94 goto out_free;
95
96 rcu_assign_pointer(net->gen, ng);
97out:
98 return net;
99
100out_free:
101 kfree(ng);
102 goto out;
84} 103}
85 104
86static void net_free(struct net *net) 105static void net_free(struct net *net)
87{ 106{
88 if (!net)
89 return;
90
91#ifdef NETNS_REFCNT_DEBUG 107#ifdef NETNS_REFCNT_DEBUG
92 if (unlikely(atomic_read(&net->use_count) != 0)) { 108 if (unlikely(atomic_read(&net->use_count) != 0)) {
93 printk(KERN_EMERG "network namespace not free! Usage: %d\n", 109 printk(KERN_EMERG "network namespace not free! Usage: %d\n",
@@ -112,27 +128,28 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
112 err = -ENOMEM; 128 err = -ENOMEM;
113 new_net = net_alloc(); 129 new_net = net_alloc();
114 if (!new_net) 130 if (!new_net)
115 goto out; 131 goto out_err;
116 132
117 mutex_lock(&net_mutex); 133 mutex_lock(&net_mutex);
118 err = setup_net(new_net); 134 err = setup_net(new_net);
119 if (err) 135 if (!err) {
120 goto out_unlock; 136 rtnl_lock();
121 137 list_add_tail(&new_net->list, &net_namespace_list);
122 rtnl_lock(); 138 rtnl_unlock();
123 list_add_tail(&new_net->list, &net_namespace_list); 139 }
124 rtnl_unlock();
125
126
127out_unlock:
128 mutex_unlock(&net_mutex); 140 mutex_unlock(&net_mutex);
141
142 if (err)
143 goto out_free;
129out: 144out:
130 put_net(old_net); 145 put_net(old_net);
131 if (err) {
132 net_free(new_net);
133 new_net = ERR_PTR(err);
134 }
135 return new_net; 146 return new_net;
147
148out_free:
149 net_free(new_net);
150out_err:
151 new_net = ERR_PTR(err);
152 goto out;
136} 153}
137 154
138static void cleanup_net(struct work_struct *work) 155static void cleanup_net(struct work_struct *work)
@@ -185,6 +202,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
185 202
186static int __init net_ns_init(void) 203static int __init net_ns_init(void)
187{ 204{
205 struct net_generic *ng;
188 int err; 206 int err;
189 207
190 printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net)); 208 printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
@@ -199,6 +217,12 @@ static int __init net_ns_init(void)
199 panic("Could not create netns workq"); 217 panic("Could not create netns workq");
200#endif 218#endif
201 219
220 ng = net_alloc_generic();
221 if (!ng)
222 panic("Could not allocate generic netns");
223
224 rcu_assign_pointer(init_net.gen, ng);
225
202 mutex_lock(&net_mutex); 226 mutex_lock(&net_mutex);
203 err = setup_net(&init_net); 227 err = setup_net(&init_net);
204 228
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index e5a8351ff12d..33640d99c8ed 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -146,14 +146,6 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
146} 146}
147EXPORT_SYMBOL(skb_under_panic); 147EXPORT_SYMBOL(skb_under_panic);
148 148
149void skb_truesize_bug(struct sk_buff *skb)
150{
151 WARN(net_ratelimit(), KERN_ERR "SKB BUG: Invalid truesize (%u) "
152 "len=%u, sizeof(sk_buff)=%Zd\n",
153 skb->truesize, skb->len, sizeof(struct sk_buff));
154}
155EXPORT_SYMBOL(skb_truesize_bug);
156
157/* Allocate a new skbuff. We do this ourselves so we can fill in a few 149/* Allocate a new skbuff. We do this ourselves so we can fill in a few
158 * 'private' fields and also do memory statistics to find all the 150 * 'private' fields and also do memory statistics to find all the
159 * [BEEP] leaks. 151 * [BEEP] leaks.
diff --git a/net/core/sock.c b/net/core/sock.c
index 40887e76652c..8ee734ea5229 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -725,7 +725,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
725 if (len < 0) 725 if (len < 0)
726 return -EINVAL; 726 return -EINVAL;
727 727
728 v.val = 0; 728 memset(&v, 0, sizeof(v));
729 729
730 switch(optname) { 730 switch(optname) {
731 case SO_DEBUG: 731 case SO_DEBUG:
@@ -1185,7 +1185,6 @@ void sock_rfree(struct sk_buff *skb)
1185{ 1185{
1186 struct sock *sk = skb->sk; 1186 struct sock *sk = skb->sk;
1187 1187
1188 skb_truesize_check(skb);
1189 atomic_sub(skb->truesize, &sk->sk_rmem_alloc); 1188 atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
1190 sk_mem_uncharge(skb->sk, skb->truesize); 1189 sk_mem_uncharge(skb->sk, skb->truesize);
1191} 1190}