diff options
-rw-r--r-- | net/batman-adv/hard-interface.c | 3 | ||||
-rw-r--r-- | net/batman-adv/main.c | 1 | ||||
-rw-r--r-- | net/batman-adv/main.h | 1 | ||||
-rw-r--r-- | net/batman-adv/netlink.c | 24 |
4 files changed, 19 insertions, 10 deletions
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 781c5b6e6e8e..508f4416dfc9 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -951,6 +951,7 @@ batadv_hardif_add_interface(struct net_device *net_dev) | |||
951 | batadv_check_known_mac_addr(hard_iface->net_dev); | 951 | batadv_check_known_mac_addr(hard_iface->net_dev); |
952 | kref_get(&hard_iface->refcount); | 952 | kref_get(&hard_iface->refcount); |
953 | list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list); | 953 | list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list); |
954 | batadv_hardif_generation++; | ||
954 | 955 | ||
955 | return hard_iface; | 956 | return hard_iface; |
956 | 957 | ||
@@ -993,6 +994,7 @@ void batadv_hardif_remove_interfaces(void) | |||
993 | list_for_each_entry_safe(hard_iface, hard_iface_tmp, | 994 | list_for_each_entry_safe(hard_iface, hard_iface_tmp, |
994 | &batadv_hardif_list, list) { | 995 | &batadv_hardif_list, list) { |
995 | list_del_rcu(&hard_iface->list); | 996 | list_del_rcu(&hard_iface->list); |
997 | batadv_hardif_generation++; | ||
996 | batadv_hardif_remove_interface(hard_iface); | 998 | batadv_hardif_remove_interface(hard_iface); |
997 | } | 999 | } |
998 | rtnl_unlock(); | 1000 | rtnl_unlock(); |
@@ -1054,6 +1056,7 @@ static int batadv_hard_if_event(struct notifier_block *this, | |||
1054 | case NETDEV_UNREGISTER: | 1056 | case NETDEV_UNREGISTER: |
1055 | case NETDEV_PRE_TYPE_CHANGE: | 1057 | case NETDEV_PRE_TYPE_CHANGE: |
1056 | list_del_rcu(&hard_iface->list); | 1058 | list_del_rcu(&hard_iface->list); |
1059 | batadv_hardif_generation++; | ||
1057 | 1060 | ||
1058 | batadv_hardif_remove_interface(hard_iface); | 1061 | batadv_hardif_remove_interface(hard_iface); |
1059 | break; | 1062 | break; |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index c75e47826949..d1ed839fd32b 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -74,6 +74,7 @@ | |||
74 | * list traversals just rcu-locked | 74 | * list traversals just rcu-locked |
75 | */ | 75 | */ |
76 | struct list_head batadv_hardif_list; | 76 | struct list_head batadv_hardif_list; |
77 | unsigned int batadv_hardif_generation; | ||
77 | static int (*batadv_rx_handler[256])(struct sk_buff *skb, | 78 | static int (*batadv_rx_handler[256])(struct sk_buff *skb, |
78 | struct batadv_hard_iface *recv_if); | 79 | struct batadv_hard_iface *recv_if); |
79 | 80 | ||
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index b68a41190eb0..b572066325e4 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -247,6 +247,7 @@ static inline int batadv_print_vid(unsigned short vid) | |||
247 | } | 247 | } |
248 | 248 | ||
249 | extern struct list_head batadv_hardif_list; | 249 | extern struct list_head batadv_hardif_list; |
250 | extern unsigned int batadv_hardif_generation; | ||
250 | 251 | ||
251 | extern unsigned char batadv_broadcast_addr[]; | 252 | extern unsigned char batadv_broadcast_addr[]; |
252 | extern struct workqueue_struct *batadv_event_workqueue; | 253 | extern struct workqueue_struct *batadv_event_workqueue; |
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 0d9459b69bdb..2dc3304cee54 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c | |||
@@ -29,11 +29,11 @@ | |||
29 | #include <linux/if_ether.h> | 29 | #include <linux/if_ether.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/list.h> | ||
32 | #include <linux/netdevice.h> | 33 | #include <linux/netdevice.h> |
33 | #include <linux/netlink.h> | 34 | #include <linux/netlink.h> |
34 | #include <linux/printk.h> | 35 | #include <linux/printk.h> |
35 | #include <linux/rculist.h> | 36 | #include <linux/rtnetlink.h> |
36 | #include <linux/rcupdate.h> | ||
37 | #include <linux/skbuff.h> | 37 | #include <linux/skbuff.h> |
38 | #include <linux/stddef.h> | 38 | #include <linux/stddef.h> |
39 | #include <linux/types.h> | 39 | #include <linux/types.h> |
@@ -445,23 +445,27 @@ out: | |||
445 | * batadv_netlink_dump_hardif_entry() - Dump one hard interface into a message | 445 | * batadv_netlink_dump_hardif_entry() - Dump one hard interface into a message |
446 | * @msg: Netlink message to dump into | 446 | * @msg: Netlink message to dump into |
447 | * @portid: Port making netlink request | 447 | * @portid: Port making netlink request |
448 | * @seq: Sequence number of netlink message | 448 | * @cb: Control block containing additional options |
449 | * @hard_iface: Hard interface to dump | 449 | * @hard_iface: Hard interface to dump |
450 | * | 450 | * |
451 | * Return: error code, or 0 on success | 451 | * Return: error code, or 0 on success |
452 | */ | 452 | */ |
453 | static int | 453 | static int |
454 | batadv_netlink_dump_hardif_entry(struct sk_buff *msg, u32 portid, u32 seq, | 454 | batadv_netlink_dump_hardif_entry(struct sk_buff *msg, u32 portid, |
455 | struct netlink_callback *cb, | ||
455 | struct batadv_hard_iface *hard_iface) | 456 | struct batadv_hard_iface *hard_iface) |
456 | { | 457 | { |
457 | struct net_device *net_dev = hard_iface->net_dev; | 458 | struct net_device *net_dev = hard_iface->net_dev; |
458 | void *hdr; | 459 | void *hdr; |
459 | 460 | ||
460 | hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI, | 461 | hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq, |
462 | &batadv_netlink_family, NLM_F_MULTI, | ||
461 | BATADV_CMD_GET_HARDIFS); | 463 | BATADV_CMD_GET_HARDIFS); |
462 | if (!hdr) | 464 | if (!hdr) |
463 | return -EMSGSIZE; | 465 | return -EMSGSIZE; |
464 | 466 | ||
467 | genl_dump_check_consistent(cb, hdr); | ||
468 | |||
465 | if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, | 469 | if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, |
466 | net_dev->ifindex) || | 470 | net_dev->ifindex) || |
467 | nla_put_string(msg, BATADV_ATTR_HARD_IFNAME, | 471 | nla_put_string(msg, BATADV_ATTR_HARD_IFNAME, |
@@ -498,7 +502,6 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb) | |||
498 | struct batadv_hard_iface *hard_iface; | 502 | struct batadv_hard_iface *hard_iface; |
499 | int ifindex; | 503 | int ifindex; |
500 | int portid = NETLINK_CB(cb->skb).portid; | 504 | int portid = NETLINK_CB(cb->skb).portid; |
501 | int seq = cb->nlh->nlmsg_seq; | ||
502 | int skip = cb->args[0]; | 505 | int skip = cb->args[0]; |
503 | int i = 0; | 506 | int i = 0; |
504 | 507 | ||
@@ -516,23 +519,24 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb) | |||
516 | return -ENODEV; | 519 | return -ENODEV; |
517 | } | 520 | } |
518 | 521 | ||
519 | rcu_read_lock(); | 522 | rtnl_lock(); |
523 | cb->seq = batadv_hardif_generation << 1 | 1; | ||
520 | 524 | ||
521 | list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { | 525 | list_for_each_entry(hard_iface, &batadv_hardif_list, list) { |
522 | if (hard_iface->soft_iface != soft_iface) | 526 | if (hard_iface->soft_iface != soft_iface) |
523 | continue; | 527 | continue; |
524 | 528 | ||
525 | if (i++ < skip) | 529 | if (i++ < skip) |
526 | continue; | 530 | continue; |
527 | 531 | ||
528 | if (batadv_netlink_dump_hardif_entry(msg, portid, seq, | 532 | if (batadv_netlink_dump_hardif_entry(msg, portid, cb, |
529 | hard_iface)) { | 533 | hard_iface)) { |
530 | i--; | 534 | i--; |
531 | break; | 535 | break; |
532 | } | 536 | } |
533 | } | 537 | } |
534 | 538 | ||
535 | rcu_read_unlock(); | 539 | rtnl_unlock(); |
536 | 540 | ||
537 | dev_put(soft_iface); | 541 | dev_put(soft_iface); |
538 | 542 | ||