aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c5
-rw-r--r--net/core/drop_monitor.c124
-rw-r--r--net/core/fib_rules.c2
-rw-r--r--net/core/net-traces.c4
-rw-r--r--net/core/net_namespace.c7
-rw-r--r--net/core/netpoll.c2
-rw-r--r--net/decnet/dn_rules.c2
-rw-r--r--net/ipv4/fib_rules.c2
-rw-r--r--net/ipv6/fib6_rules.c2
-rw-r--r--net/ipv6/tcp_ipv6.c7
-rw-r--r--net/irda/irnetlink.c17
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c18
-rw-r--r--net/netlabel/netlabel_cipso_v4.c16
-rw-r--r--net/netlabel/netlabel_mgmt.c16
-rw-r--r--net/netlabel/netlabel_unlabeled.c16
-rw-r--r--net/netlink/genetlink.c46
-rw-r--r--net/packet/af_packet.c10
-rw-r--r--net/tipc/netlink.c38
-rw-r--r--net/wireless/nl80211.c11
19 files changed, 222 insertions, 123 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 92ebeca29901..3942266d1f6c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -126,6 +126,7 @@
126#include <linux/in.h> 126#include <linux/in.h>
127#include <linux/jhash.h> 127#include <linux/jhash.h>
128#include <linux/random.h> 128#include <linux/random.h>
129#include <trace/napi.h>
129 130
130#include "net-sysfs.h" 131#include "net-sysfs.h"
131 132
@@ -2771,8 +2772,10 @@ static void net_rx_action(struct softirq_action *h)
2771 * accidently calling ->poll() when NAPI is not scheduled. 2772 * accidently calling ->poll() when NAPI is not scheduled.
2772 */ 2773 */
2773 work = 0; 2774 work = 0;
2774 if (test_bit(NAPI_STATE_SCHED, &n->state)) 2775 if (test_bit(NAPI_STATE_SCHED, &n->state)) {
2775 work = n->poll(n, weight); 2776 work = n->poll(n, weight);
2777 trace_napi_poll(n);
2778 }
2776 2779
2777 WARN_ON_ONCE(work > weight); 2780 WARN_ON_ONCE(work > weight);
2778 2781
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 2797b711a978..a6c2ac2828fb 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -22,8 +22,10 @@
22#include <linux/timer.h> 22#include <linux/timer.h>
23#include <linux/bitops.h> 23#include <linux/bitops.h>
24#include <net/genetlink.h> 24#include <net/genetlink.h>
25#include <net/netevent.h>
25 26
26#include <trace/skb.h> 27#include <trace/skb.h>
28#include <trace/napi.h>
27 29
28#include <asm/unaligned.h> 30#include <asm/unaligned.h>
29 31
@@ -38,7 +40,8 @@ static void send_dm_alert(struct work_struct *unused);
38 * and the work handle that will send up 40 * and the work handle that will send up
39 * netlink alerts 41 * netlink alerts
40 */ 42 */
41struct sock *dm_sock; 43static int trace_state = TRACE_OFF;
44static spinlock_t trace_state_lock = SPIN_LOCK_UNLOCKED;
42 45
43struct per_cpu_dm_data { 46struct per_cpu_dm_data {
44 struct work_struct dm_alert_work; 47 struct work_struct dm_alert_work;
@@ -47,6 +50,13 @@ struct per_cpu_dm_data {
47 struct timer_list send_timer; 50 struct timer_list send_timer;
48}; 51};
49 52
53struct dm_hw_stat_delta {
54 struct net_device *dev;
55 struct list_head list;
56 struct rcu_head rcu;
57 unsigned long last_drop_val;
58};
59
50static struct genl_family net_drop_monitor_family = { 60static struct genl_family net_drop_monitor_family = {
51 .id = GENL_ID_GENERATE, 61 .id = GENL_ID_GENERATE,
52 .hdrsize = 0, 62 .hdrsize = 0,
@@ -59,7 +69,8 @@ static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data);
59 69
60static int dm_hit_limit = 64; 70static int dm_hit_limit = 64;
61static int dm_delay = 1; 71static int dm_delay = 1;
62 72static unsigned long dm_hw_check_delta = 2*HZ;
73static LIST_HEAD(hw_stats_list);
63 74
64static void reset_per_cpu_data(struct per_cpu_dm_data *data) 75static void reset_per_cpu_data(struct per_cpu_dm_data *data)
65{ 76{
@@ -115,7 +126,7 @@ static void sched_send_work(unsigned long unused)
115 schedule_work(&data->dm_alert_work); 126 schedule_work(&data->dm_alert_work);
116} 127}
117 128
118static void trace_kfree_skb_hit(struct sk_buff *skb, void *location) 129static void trace_drop_common(struct sk_buff *skb, void *location)
119{ 130{
120 struct net_dm_alert_msg *msg; 131 struct net_dm_alert_msg *msg;
121 struct nlmsghdr *nlh; 132 struct nlmsghdr *nlh;
@@ -159,24 +170,80 @@ out:
159 return; 170 return;
160} 171}
161 172
173static void trace_kfree_skb_hit(struct sk_buff *skb, void *location)
174{
175 trace_drop_common(skb, location);
176}
177
178static void trace_napi_poll_hit(struct napi_struct *napi)
179{
180 struct dm_hw_stat_delta *new_stat;
181
182 /*
183 * Ratelimit our check time to dm_hw_check_delta jiffies
184 */
185 if (!time_after(jiffies, napi->dev->last_rx + dm_hw_check_delta))
186 return;
187
188 rcu_read_lock();
189 list_for_each_entry_rcu(new_stat, &hw_stats_list, list) {
190 if ((new_stat->dev == napi->dev) &&
191 (napi->dev->stats.rx_dropped != new_stat->last_drop_val)) {
192 trace_drop_common(NULL, NULL);
193 new_stat->last_drop_val = napi->dev->stats.rx_dropped;
194 break;
195 }
196 }
197 rcu_read_unlock();
198}
199
200
201static void free_dm_hw_stat(struct rcu_head *head)
202{
203 struct dm_hw_stat_delta *n;
204 n = container_of(head, struct dm_hw_stat_delta, rcu);
205 kfree(n);
206}
207
162static int set_all_monitor_traces(int state) 208static int set_all_monitor_traces(int state)
163{ 209{
164 int rc = 0; 210 int rc = 0;
211 struct dm_hw_stat_delta *new_stat = NULL;
212 struct dm_hw_stat_delta *temp;
213
214 spin_lock(&trace_state_lock);
165 215
166 switch (state) { 216 switch (state) {
167 case TRACE_ON: 217 case TRACE_ON:
168 rc |= register_trace_kfree_skb(trace_kfree_skb_hit); 218 rc |= register_trace_kfree_skb(trace_kfree_skb_hit);
219 rc |= register_trace_napi_poll(trace_napi_poll_hit);
169 break; 220 break;
170 case TRACE_OFF: 221 case TRACE_OFF:
171 rc |= unregister_trace_kfree_skb(trace_kfree_skb_hit); 222 rc |= unregister_trace_kfree_skb(trace_kfree_skb_hit);
223 rc |= unregister_trace_napi_poll(trace_napi_poll_hit);
172 224
173 tracepoint_synchronize_unregister(); 225 tracepoint_synchronize_unregister();
226
227 /*
228 * Clean the device list
229 */
230 list_for_each_entry_safe(new_stat, temp, &hw_stats_list, list) {
231 if (new_stat->dev == NULL) {
232 list_del_rcu(&new_stat->list);
233 call_rcu(&new_stat->rcu, free_dm_hw_stat);
234 }
235 }
174 break; 236 break;
175 default: 237 default:
176 rc = 1; 238 rc = 1;
177 break; 239 break;
178 } 240 }
179 241
242 if (!rc)
243 trace_state = state;
244
245 spin_unlock(&trace_state_lock);
246
180 if (rc) 247 if (rc)
181 return -EINPROGRESS; 248 return -EINPROGRESS;
182 return rc; 249 return rc;
@@ -204,6 +271,44 @@ static int net_dm_cmd_trace(struct sk_buff *skb,
204 return -ENOTSUPP; 271 return -ENOTSUPP;
205} 272}
206 273
274static int dropmon_net_event(struct notifier_block *ev_block,
275 unsigned long event, void *ptr)
276{
277 struct net_device *dev = ptr;
278 struct dm_hw_stat_delta *new_stat = NULL;
279 struct dm_hw_stat_delta *tmp;
280
281 switch (event) {
282 case NETDEV_REGISTER:
283 new_stat = kzalloc(sizeof(struct dm_hw_stat_delta), GFP_KERNEL);
284
285 if (!new_stat)
286 goto out;
287
288 new_stat->dev = dev;
289 INIT_RCU_HEAD(&new_stat->rcu);
290 spin_lock(&trace_state_lock);
291 list_add_rcu(&new_stat->list, &hw_stats_list);
292 spin_unlock(&trace_state_lock);
293 break;
294 case NETDEV_UNREGISTER:
295 spin_lock(&trace_state_lock);
296 list_for_each_entry_safe(new_stat, tmp, &hw_stats_list, list) {
297 if (new_stat->dev == dev) {
298 new_stat->dev = NULL;
299 if (trace_state == TRACE_OFF) {
300 list_del_rcu(&new_stat->list);
301 call_rcu(&new_stat->rcu, free_dm_hw_stat);
302 break;
303 }
304 }
305 }
306 spin_unlock(&trace_state_lock);
307 break;
308 }
309out:
310 return NOTIFY_DONE;
311}
207 312
208static struct genl_ops dropmon_ops[] = { 313static struct genl_ops dropmon_ops[] = {
209 { 314 {
@@ -220,6 +325,10 @@ static struct genl_ops dropmon_ops[] = {
220 }, 325 },
221}; 326};
222 327
328static struct notifier_block dropmon_net_notifier = {
329 .notifier_call = dropmon_net_event
330};
331
223static int __init init_net_drop_monitor(void) 332static int __init init_net_drop_monitor(void)
224{ 333{
225 int cpu; 334 int cpu;
@@ -243,12 +352,18 @@ static int __init init_net_drop_monitor(void)
243 ret = genl_register_ops(&net_drop_monitor_family, 352 ret = genl_register_ops(&net_drop_monitor_family,
244 &dropmon_ops[i]); 353 &dropmon_ops[i]);
245 if (ret) { 354 if (ret) {
246 printk(KERN_CRIT "failed to register operation %d\n", 355 printk(KERN_CRIT "Failed to register operation %d\n",
247 dropmon_ops[i].cmd); 356 dropmon_ops[i].cmd);
248 goto out_unreg; 357 goto out_unreg;
249 } 358 }
250 } 359 }
251 360
361 rc = register_netdevice_notifier(&dropmon_net_notifier);
362 if (rc < 0) {
363 printk(KERN_CRIT "Failed to register netdevice notifier\n");
364 goto out_unreg;
365 }
366
252 rc = 0; 367 rc = 0;
253 368
254 for_each_present_cpu(cpu) { 369 for_each_present_cpu(cpu) {
@@ -259,6 +374,7 @@ static int __init init_net_drop_monitor(void)
259 data->send_timer.data = cpu; 374 data->send_timer.data = cpu;
260 data->send_timer.function = sched_send_work; 375 data->send_timer.function = sched_send_work;
261 } 376 }
377
262 goto out; 378 goto out;
263 379
264out_unreg: 380out_unreg:
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 17d9f497b797..bd309384f8b8 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -500,7 +500,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
500 if (rule->target) 500 if (rule->target)
501 NLA_PUT_U32(skb, FRA_GOTO, rule->target); 501 NLA_PUT_U32(skb, FRA_GOTO, rule->target);
502 502
503 if (ops->fill(rule, skb, nlh, frh) < 0) 503 if (ops->fill(rule, skb, frh) < 0)
504 goto nla_put_failure; 504 goto nla_put_failure;
505 505
506 return nlmsg_end(skb, nlh); 506 return nlmsg_end(skb, nlh);
diff --git a/net/core/net-traces.c b/net/core/net-traces.c
index c8fb45665e4f..b07b25bd2cde 100644
--- a/net/core/net-traces.c
+++ b/net/core/net-traces.c
@@ -20,6 +20,7 @@
20#include <linux/netlink.h> 20#include <linux/netlink.h>
21#include <linux/net_dropmon.h> 21#include <linux/net_dropmon.h>
22#include <trace/skb.h> 22#include <trace/skb.h>
23#include <trace/napi.h>
23 24
24#include <asm/unaligned.h> 25#include <asm/unaligned.h>
25#include <asm/bitops.h> 26#include <asm/bitops.h>
@@ -27,3 +28,6 @@
27 28
28DEFINE_TRACE(kfree_skb); 29DEFINE_TRACE(kfree_skb);
29EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb); 30EXPORT_TRACEPOINT_SYMBOL_GPL(kfree_skb);
31
32DEFINE_TRACE(napi_poll);
33EXPORT_TRACEPOINT_SYMBOL_GPL(napi_poll);
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 6b3edc9e6f19..b7292a2719dc 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -196,9 +196,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
196static int __init net_ns_init(void) 196static int __init net_ns_init(void)
197{ 197{
198 struct net_generic *ng; 198 struct net_generic *ng;
199 int err;
200 199
201 printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
202#ifdef CONFIG_NET_NS 200#ifdef CONFIG_NET_NS
203 net_cachep = kmem_cache_create("net_namespace", sizeof(struct net), 201 net_cachep = kmem_cache_create("net_namespace", sizeof(struct net),
204 SMP_CACHE_BYTES, 202 SMP_CACHE_BYTES,
@@ -217,15 +215,14 @@ static int __init net_ns_init(void)
217 rcu_assign_pointer(init_net.gen, ng); 215 rcu_assign_pointer(init_net.gen, ng);
218 216
219 mutex_lock(&net_mutex); 217 mutex_lock(&net_mutex);
220 err = setup_net(&init_net); 218 if (setup_net(&init_net))
219 panic("Could not setup the initial network namespace");
221 220
222 rtnl_lock(); 221 rtnl_lock();
223 list_add_tail(&init_net.list, &net_namespace_list); 222 list_add_tail(&init_net.list, &net_namespace_list);
224 rtnl_unlock(); 223 rtnl_unlock();
225 224
226 mutex_unlock(&net_mutex); 225 mutex_unlock(&net_mutex);
227 if (err)
228 panic("Could not setup the initial network namespace");
229 226
230 return 0; 227 return 0;
231} 228}
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 64f51eec6576..67b4f3e3d4a5 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -24,6 +24,7 @@
24#include <net/tcp.h> 24#include <net/tcp.h>
25#include <net/udp.h> 25#include <net/udp.h>
26#include <asm/unaligned.h> 26#include <asm/unaligned.h>
27#include <trace/napi.h>
27 28
28/* 29/*
29 * We maintain a small pool of fully-sized skbs, to make sure the 30 * We maintain a small pool of fully-sized skbs, to make sure the
@@ -137,6 +138,7 @@ static int poll_one_napi(struct netpoll_info *npinfo,
137 set_bit(NAPI_STATE_NPSVC, &napi->state); 138 set_bit(NAPI_STATE_NPSVC, &napi->state);
138 139
139 work = napi->poll(napi, budget); 140 work = napi->poll(napi, budget);
141 trace_napi_poll(napi);
140 142
141 clear_bit(NAPI_STATE_NPSVC, &napi->state); 143 clear_bit(NAPI_STATE_NPSVC, &napi->state);
142 atomic_dec(&trapped); 144 atomic_dec(&trapped);
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index a2690b12e03c..72495f25269f 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -192,7 +192,7 @@ unsigned dnet_addr_type(__le16 addr)
192} 192}
193 193
194static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb, 194static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
195 struct nlmsghdr *nlh, struct fib_rule_hdr *frh) 195 struct fib_rule_hdr *frh)
196{ 196{
197 struct dn_fib_rule *r = (struct dn_fib_rule *)rule; 197 struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
198 198
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 38904be4102e..92d9d97ec5e3 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -209,7 +209,7 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
209} 209}
210 210
211static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb, 211static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
212 struct nlmsghdr *nlh, struct fib_rule_hdr *frh) 212 struct fib_rule_hdr *frh)
213{ 213{
214 struct fib4_rule *rule4 = (struct fib4_rule *) rule; 214 struct fib4_rule *rule4 = (struct fib4_rule *) rule;
215 215
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index e1a36dbb5a27..00a7a5e4ac97 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -211,7 +211,7 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
211} 211}
212 212
213static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, 213static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
214 struct nlmsghdr *nlh, struct fib_rule_hdr *frh) 214 struct fib_rule_hdr *frh)
215{ 215{
216 struct fib6_rule *rule6 = (struct fib6_rule *) rule; 216 struct fib6_rule *rule6 = (struct fib6_rule *) rule;
217 217
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index d9dd94b6bf66..ea37741062a9 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -941,7 +941,8 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb)
941 return 0; 941 return 0;
942} 942}
943 943
944struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb) 944static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
945 struct sk_buff *skb)
945{ 946{
946 struct ipv6hdr *iph = skb_gro_network_header(skb); 947 struct ipv6hdr *iph = skb_gro_network_header(skb);
947 948
@@ -961,9 +962,8 @@ struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb)
961 962
962 return tcp_gro_receive(head, skb); 963 return tcp_gro_receive(head, skb);
963} 964}
964EXPORT_SYMBOL(tcp6_gro_receive);
965 965
966int tcp6_gro_complete(struct sk_buff *skb) 966static int tcp6_gro_complete(struct sk_buff *skb)
967{ 967{
968 struct ipv6hdr *iph = ipv6_hdr(skb); 968 struct ipv6hdr *iph = ipv6_hdr(skb);
969 struct tcphdr *th = tcp_hdr(skb); 969 struct tcphdr *th = tcp_hdr(skb);
@@ -974,7 +974,6 @@ int tcp6_gro_complete(struct sk_buff *skb)
974 974
975 return tcp_gro_complete(skb); 975 return tcp_gro_complete(skb);
976} 976}
977EXPORT_SYMBOL(tcp6_gro_complete);
978 977
979static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, 978static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
980 u32 ts, struct tcp_md5sig_key *key, int rst) 979 u32 ts, struct tcp_md5sig_key *key, int rst)
diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c
index 82c6118d82c6..8dd7ed7e7c1f 100644
--- a/net/irda/irnetlink.c
+++ b/net/irda/irnetlink.c
@@ -148,21 +148,8 @@ static struct genl_ops irda_nl_ops[] = {
148 148
149int irda_nl_register(void) 149int irda_nl_register(void)
150{ 150{
151 int err, i; 151 return genl_register_family_with_ops(&irda_nl_family,
152 152 irda_nl_ops, ARRAY_SIZE(irda_nl_ops));
153 err = genl_register_family(&irda_nl_family);
154 if (err)
155 return err;
156
157 for (i = 0; i < ARRAY_SIZE(irda_nl_ops); i++) {
158 err = genl_register_ops(&irda_nl_family, &irda_nl_ops[i]);
159 if (err)
160 goto err_out;
161 }
162 return 0;
163 err_out:
164 genl_unregister_family(&irda_nl_family);
165 return err;
166} 153}
167 154
168void irda_nl_unregister(void) 155void irda_nl_unregister(void)
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index e01061f49cdc..7c1333c67ff3 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3345,22 +3345,8 @@ static struct genl_ops ip_vs_genl_ops[] __read_mostly = {
3345 3345
3346static int __init ip_vs_genl_register(void) 3346static int __init ip_vs_genl_register(void)
3347{ 3347{
3348 int ret, i; 3348 return genl_register_family_with_ops(&ip_vs_genl_family,
3349 3349 ip_vs_genl_ops, ARRAY_SIZE(ip_vs_genl_ops));
3350 ret = genl_register_family(&ip_vs_genl_family);
3351 if (ret)
3352 return ret;
3353
3354 for (i = 0; i < ARRAY_SIZE(ip_vs_genl_ops); i++) {
3355 ret = genl_register_ops(&ip_vs_genl_family, &ip_vs_genl_ops[i]);
3356 if (ret)
3357 goto err_out;
3358 }
3359 return 0;
3360
3361err_out:
3362 genl_unregister_family(&ip_vs_genl_family);
3363 return ret;
3364} 3350}
3365 3351
3366static void ip_vs_genl_unregister(void) 3352static void ip_vs_genl_unregister(void)
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index bf1ab1a6790d..e639298bc9c8 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -785,18 +785,6 @@ static struct genl_ops netlbl_cipsov4_ops[] = {
785 */ 785 */
786int __init netlbl_cipsov4_genl_init(void) 786int __init netlbl_cipsov4_genl_init(void)
787{ 787{
788 int ret_val, i; 788 return genl_register_family_with_ops(&netlbl_cipsov4_gnl_family,
789 789 netlbl_cipsov4_ops, ARRAY_SIZE(netlbl_cipsov4_ops));
790 ret_val = genl_register_family(&netlbl_cipsov4_gnl_family);
791 if (ret_val != 0)
792 return ret_val;
793
794 for (i = 0; i < ARRAY_SIZE(netlbl_cipsov4_ops); i++) {
795 ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
796 &netlbl_cipsov4_ops[i]);
797 if (ret_val != 0)
798 return ret_val;
799 }
800
801 return 0;
802} 790}
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index 1821c5d50fb8..8203623e65ad 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -779,18 +779,6 @@ static struct genl_ops netlbl_mgmt_genl_ops[] = {
779 */ 779 */
780int __init netlbl_mgmt_genl_init(void) 780int __init netlbl_mgmt_genl_init(void)
781{ 781{
782 int ret_val, i; 782 return genl_register_family_with_ops(&netlbl_mgmt_gnl_family,
783 783 netlbl_mgmt_genl_ops, ARRAY_SIZE(netlbl_mgmt_genl_ops));
784 ret_val = genl_register_family(&netlbl_mgmt_gnl_family);
785 if (ret_val != 0)
786 return ret_val;
787
788 for (i = 0; i < ARRAY_SIZE(netlbl_mgmt_genl_ops); i++) {
789 ret_val = genl_register_ops(&netlbl_mgmt_gnl_family,
790 &netlbl_mgmt_genl_ops[i]);
791 if (ret_val != 0)
792 return ret_val;
793 }
794
795 return 0;
796} 784}
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index f3c5c68c6848..fb357f010189 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -1478,20 +1478,8 @@ static struct genl_ops netlbl_unlabel_genl_ops[] = {
1478 */ 1478 */
1479int __init netlbl_unlabel_genl_init(void) 1479int __init netlbl_unlabel_genl_init(void)
1480{ 1480{
1481 int ret_val, i; 1481 return genl_register_family_with_ops(&netlbl_unlabel_gnl_family,
1482 1482 netlbl_unlabel_genl_ops, ARRAY_SIZE(netlbl_unlabel_genl_ops));
1483 ret_val = genl_register_family(&netlbl_unlabel_gnl_family);
1484 if (ret_val != 0)
1485 return ret_val;
1486
1487 for (i = 0; i < ARRAY_SIZE(netlbl_unlabel_genl_ops); i++) {
1488 ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
1489 &netlbl_unlabel_genl_ops[i]);
1490 if (ret_val != 0)
1491 return ret_val;
1492 }
1493
1494 return 0;
1495} 1483}
1496 1484
1497/* 1485/*
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 1d3dd30099df..eed4c6a8afc0 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -384,6 +384,52 @@ errout:
384} 384}
385 385
386/** 386/**
387 * genl_register_family_with_ops - register a generic netlink family
388 * @family: generic netlink family
389 * @ops: operations to be registered
390 * @n_ops: number of elements to register
391 *
392 * Registers the specified family and operations from the specified table.
393 * Only one family may be registered with the same family name or identifier.
394 *
395 * The family id may equal GENL_ID_GENERATE causing an unique id to
396 * be automatically generated and assigned.
397 *
398 * Either a doit or dumpit callback must be specified for every registered
399 * operation or the function will fail. Only one operation structure per
400 * command identifier may be registered.
401 *
402 * See include/net/genetlink.h for more documenation on the operations
403 * structure.
404 *
405 * This is equivalent to calling genl_register_family() followed by
406 * genl_register_ops() for every operation entry in the table taking
407 * care to unregister the family on error path.
408 *
409 * Return 0 on success or a negative error code.
410 */
411int genl_register_family_with_ops(struct genl_family *family,
412 struct genl_ops *ops, size_t n_ops)
413{
414 int err, i;
415
416 err = genl_register_family(family);
417 if (err)
418 return err;
419
420 for (i = 0; i < n_ops; ++i, ++ops) {
421 err = genl_register_ops(family, ops);
422 if (err)
423 goto err_out;
424 }
425 return 0;
426err_out:
427 genl_unregister_family(family);
428 return err;
429}
430EXPORT_SYMBOL(genl_register_family_with_ops);
431
432/**
387 * genl_unregister_family - unregister generic netlink family 433 * genl_unregister_family - unregister generic netlink family
388 * @family: generic netlink family 434 * @family: generic netlink family
389 * 435 *
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 766e6b41f7ca..c7c5d524967e 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1570,9 +1570,9 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i,
1570 switch (i->type) { 1570 switch (i->type) {
1571 case PACKET_MR_MULTICAST: 1571 case PACKET_MR_MULTICAST:
1572 if (what > 0) 1572 if (what > 0)
1573 dev_mc_add(dev, i->addr, i->alen, 0); 1573 return dev_mc_add(dev, i->addr, i->alen, 0);
1574 else 1574 else
1575 dev_mc_delete(dev, i->addr, i->alen, 0); 1575 return dev_mc_delete(dev, i->addr, i->alen, 0);
1576 break; 1576 break;
1577 case PACKET_MR_PROMISC: 1577 case PACKET_MR_PROMISC:
1578 return dev_set_promiscuity(dev, what); 1578 return dev_set_promiscuity(dev, what);
@@ -1580,6 +1580,12 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i,
1580 case PACKET_MR_ALLMULTI: 1580 case PACKET_MR_ALLMULTI:
1581 return dev_set_allmulti(dev, what); 1581 return dev_set_allmulti(dev, what);
1582 break; 1582 break;
1583 case PACKET_MR_UNICAST:
1584 if (what > 0)
1585 return dev_unicast_add(dev, i->addr, i->alen);
1586 else
1587 return dev_unicast_delete(dev, i->addr, i->alen);
1588 break;
1583 default:; 1589 default:;
1584 } 1590 }
1585 return 0; 1591 return 0;
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index c387217bb230..3c57005e44d1 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -68,7 +68,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
68 return 0; 68 return 0;
69} 69}
70 70
71static struct genl_family family = { 71static struct genl_family tipc_genl_family = {
72 .id = GENL_ID_GENERATE, 72 .id = GENL_ID_GENERATE,
73 .name = TIPC_GENL_NAME, 73 .name = TIPC_GENL_NAME,
74 .version = TIPC_GENL_VERSION, 74 .version = TIPC_GENL_VERSION,
@@ -76,39 +76,33 @@ static struct genl_family family = {
76 .maxattr = 0, 76 .maxattr = 0,
77}; 77};
78 78
79static struct genl_ops ops = { 79static struct genl_ops tipc_genl_ops = {
80 .cmd = TIPC_GENL_CMD, 80 .cmd = TIPC_GENL_CMD,
81 .doit = handle_cmd, 81 .doit = handle_cmd,
82}; 82};
83 83
84static int family_registered = 0; 84static int tipc_genl_family_registered;
85 85
86int tipc_netlink_start(void) 86int tipc_netlink_start(void)
87{ 87{
88 int res;
88 89
90 res = genl_register_family_with_ops(&tipc_genl_family,
91 &tipc_genl_ops, 1);
92 if (res) {
93 err("Failed to register netlink interface\n");
94 return res;
95 }
89 96
90 if (genl_register_family(&family)) 97 tipc_genl_family_registered = 1;
91 goto err;
92
93 family_registered = 1;
94
95 if (genl_register_ops(&family, &ops))
96 goto err_unregister;
97
98 return 0; 98 return 0;
99
100 err_unregister:
101 genl_unregister_family(&family);
102 family_registered = 0;
103 err:
104 err("Failed to register netlink interface\n");
105 return -EFAULT;
106} 99}
107 100
108void tipc_netlink_stop(void) 101void tipc_netlink_stop(void)
109{ 102{
110 if (family_registered) { 103 if (!tipc_genl_family_registered)
111 genl_unregister_family(&family); 104 return;
112 family_registered = 0; 105
113 } 106 genl_unregister_family(&tipc_genl_family);
107 tipc_genl_family_registered = 0;
114} 108}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 632504060789..56d729c43b31 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3918,18 +3918,13 @@ nla_put_failure:
3918 3918
3919int nl80211_init(void) 3919int nl80211_init(void)
3920{ 3920{
3921 int err, i; 3921 int err;
3922 3922
3923 err = genl_register_family(&nl80211_fam); 3923 err = genl_register_family_with_ops(&nl80211_fam,
3924 nl80211_ops, ARRAY_SIZE(nl80211_ops));
3924 if (err) 3925 if (err)
3925 return err; 3926 return err;
3926 3927
3927 for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
3928 err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
3929 if (err)
3930 goto err_out;
3931 }
3932
3933 err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp); 3928 err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
3934 if (err) 3929 if (err)
3935 goto err_out; 3930 goto err_out;