dynamic generic netlink multicast
Subsystems (2)
cover dynamic generic netlink multicast
This patch series adds dynamic generic netlink multicast groups. The ACPI people are open to rebasing their patches on top of this. Both Jamal and Patrick gave it a quick review (Patrick said he'll review it again when he gets around) and we've discussed the API for a while ending up with this. Please apply.
johannes
PATCH 1/3 netlink: allocate group bitmaps dynamically
Allow changing the number of groups for a netlink family after it has been created, use RCU to protect the listeners bitmap keeping netlink_has_listeners() lock-free.
--- include/linux/netlink.h | 1 net/netlink/af_netlink.c | 86 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 21 deletions(-)
net/netlink/af_netlink.c +65 -21
@@ -62,6 +62,7 @@#include <net/netlink.h> #define NLGRPSZ (x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) +#define NLGRPLONGS (x) (NLGRPSZ(x)/sizeof(unsigned long))struct netlink_sock {/* struct sock has to be the first member of netlink_sock */
@@ -314,10 +315,12 @@ netlink_update_listeners(struct sock *skunsigned long mask;unsigned int i; -for (i =0 ; i <NLGRPSZ (tbl->groups)/sizeof (unsigned long ); i++) { +for (i =0 ; i <NLGRPLONGS (tbl->groups); i++) { mask =0 ; -sk_for_each_bound (sk, node, &tbl->mc_list) - mask |=nlk_sk (sk)->groups[i]; +sk_for_each_bound (sk, node, &tbl->mc_list) { +if (i <NLGRPLONGS (nlk_sk (sk)->ngroups)) + mask |=nlk_sk (sk)->groups[i]; + } tbl->listeners[i] = mask; }/* this function is only called with the netlink table "grabbed", which
@@ -555,26 +558,37 @@ netlink_update_subscriptions(struct sock nlk->subscriptions = subscriptions; } -static int netlink_alloc_groups (struct sock *sk) +static int netlink_realloc_groups (struct sock *sk) {struct netlink_sock *nlk =nlk_sk (sk);unsigned int groups; +unsigned long *new_groups;int err =0 ;netlink_lock_table (); groups = nl_table[sk->sk_protocol].groups;if (!nl_table[sk->sk_protocol].registered) err = -ENOENT ; -netlink_unlock_table ();if (err) -return err; + goto out_unlock; - nlk->groups =kzalloc (NLGRPSZ (groups),GFP_KERNEL ); -if (nlk->groups ==NULL ) -return -ENOMEM ; +if (nlk->ngroups >= groups) + goto out_unlock; + + new_groups =krealloc (nlk->groups,NLGRPSZ (groups),GFP_KERNEL ); +if (new_groups ==NULL ) { + err = -ENOMEM ; + goto out_unlock; + } +memset ((char *)new_groups +NLGRPSZ (nlk->ngroups),0 , +NLGRPSZ (groups) -NLGRPSZ (nlk->ngroups)); + + nlk->groups = new_groups; nlk->ngroups = groups; -return 0 ; + out_unlock: +netlink_unlock_table (); +return err; }static int netlink_bind (struct socket *sock,struct sockaddr *addr,int addr_len)
@@ -591,11 +605,9 @@ static int netlink_bind(struct socket *sif (nladdr->nl_groups) {if (!netlink_capable (sock,NL_NONROOT_RECV ))return -EPERM ; -if (nlk->groups ==NULL ) { - err =netlink_alloc_groups (sk); -if (err) -return err; - } + err =netlink_realloc_groups (sk); +if (err) +return err; }if (nlk->pid) {
@@ -839,10 +851,18 @@ retry:int netlink_has_listeners (struct sock *sk,unsigned int group) {int res =0 ; +unsigned long *listeners;BUG_ON (!(nlk_sk (sk)->flags &NETLINK_KERNEL_SOCKET )); + +rcu_read_lock (); + listeners =rcu_dereference (nl_table[sk->sk_protocol].listeners); +if (group -1 < nl_table[sk->sk_protocol].groups) - res =test_bit (group -1 , nl_table[sk->sk_protocol].listeners); + res =test_bit (group -1 , listeners); + +rcu_read_unlock (); +return res; }EXPORT_SYMBOL_GPL (netlink_has_listeners);
@@ -1037,11 +1057,9 @@ static int netlink_setsockopt(struct socif (!netlink_capable (sock,NL_NONROOT_RECV ))return -EPERM ; -if (nlk->groups ==NULL ) { - err =netlink_alloc_groups (sk); -if (err) -return err; - } + err =netlink_realloc_groups (sk); +if (err) +return err;if (!val || val -1 >= nlk->ngroups)return -EINVAL ;netlink_table_grab ();
@@ -1328,6 +1346,32 @@ out_sock_release:return NULL ; } +int netlink_change_ngroups (int unit,unsigned int groups) +{ +unsigned long *listeners, old =NULL ; +int err =0 ; + +netlink_table_grab (); +if (NLGRPSZ (nl_table[unit].groups) <NLGRPSZ (groups)) { + listeners =kzalloc (NLGRPSZ (groups),GFP_ATOMIC ); +if (!listeners) { + err = -ENOMEM ; + goto out_ungrab; + } + old = nl_table[unit].listeners; +memcpy (listeners, old,NLGRPSZ (nl_table[unit].groups)); +rcu_assign_pointer (nl_table[unit].listeners, listeners); + } + nl_table[unit].groups = groups; + + out_ungrab: +netlink_table_ungrab (); +synchronize_rcu (); +kfree (old); +return err; +} +EXPORT_SYMBOL (netlink_change_ngroups); +void netlink_set_nonroot (int protocol,unsigned int flags) {if ((unsigned int )protocol <MAX_LINKS )
include/linux/netlink.h +1 -0
@@ -161,6 +161,7 @@ extern struct sock *netlink_kernel_creatvoid (*input)(struct sock *sk,int len), struct mutex *cb_mutex, struct module *module); +extern int netlink_change_ngroups (int unit,unsigned int groups);extern void netlink_ack (struct sk_buff *in_skb,struct nlmsghdr *nlh,int err);extern int netlink_has_listeners (struct sock *sk,unsigned int group);extern int netlink_unicast (struct sock *ssk,struct sk_buff *skb,__u32 pid,int nonblock);
Re: [patch 1/3] netlink: allocate group bitmaps dynamically
Quoted 13 lines · Johannes Berg
Allow changing the number of groups for a netlink family after it has been created, use RCU to protect the listeners bitmap keeping
netlink_has_listeners()lock-free.Signed-off-by Johannes Berg <[email protected]>--- include/linux/netlink.h | 1 net/netlink/af_netlink.c | 86 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 21 deletions(-)
net/netlink/af_netlink.c netlink_update_subscriptions(struct sock · line 568
Quoted 9 lines
net/netlink/af_netlink.c +2
-1-static int netlink_alloc_groups (struct sock *sk) +static int netlink_realloc_groups (struct sock *sk) {struct netlink_sock *nlk =nlk_sk (sk);unsigned int groups; +unsigned long *new_groups;int err =0 ;netlink_lock_table ();
This is actually a bug in the current code I think, netlink_lock_table is a reader lock.
Quoted 23 lines
net/netlink/af_netlink.c +12
-5groups = nl_table[sk->sk_protocol].groups;if (!nl_table[sk->sk_protocol].registered) err = -ENOENT ; -netlink_unlock_table ();if (err) -return err; + goto out_unlock; - nlk->groups =kzalloc (NLGRPSZ (groups),GFP_KERNEL ); -if (nlk->groups ==NULL ) -return -ENOMEM ; +if (nlk->ngroups >= groups) + goto out_unlock; + + new_groups =krealloc (nlk->groups,NLGRPSZ (groups),GFP_KERNEL ); +if (new_groups ==NULL ) { + err = -ENOMEM ; + goto out_unlock; + } +memset ((char *)new_groups +NLGRPSZ (nlk->ngroups),0 , +NLGRPSZ (groups) -NLGRPSZ (nlk->ngroups)); +
net/netlink/af_netlink.c netlink_update_subscriptions(struct sock
Quoted 10 lines
net/netlink/af_netlink.c +5
-1+ nlk->groups = new_groups; nlk->ngroups = groups; -return 0 ; + out_unlock: +netlink_unlock_table (); +return err; } +int netlink_change_ngroups (int unit,unsigned int groups)
I think it would be more consistent to pass the kernel socket instead of the unit.
Quoted 6 lines
net/netlink/af_netlink.c +6
-0+{ +unsigned long *listeners, old =NULL ; +int err =0 ; + +netlink_table_grab (); +if (NLGRPSZ (nl_table[unit].groups) <NLGRPSZ (groups)) {
net/netlink/af_netlink.c out_sock_release: · line 1365
Quoted 10 lines
net/netlink/af_netlink.c +10
-0+ listeners =kzalloc (NLGRPSZ (groups),GFP_ATOMIC ); +if (!listeners) { + err = -ENOMEM ; + goto out_ungrab; + } + old = nl_table[unit].listeners; +memcpy (listeners, old,NLGRPSZ (nl_table[unit].groups)); +rcu_assign_pointer (nl_table[unit].listeners, listeners); + } + nl_table[unit].groups = groups;
This might set the group to a value < 32. I don't expect it matters, but when I changed to old code to support > 32 groups I enforced a minimum of 32 so anything outside the kernel multicasting on them would still work (even though its a really stupid idea). So for consistency this should probably also use a minimum of 32.
Re: [patch 1/3] netlink: allocate group bitmaps dynamically
Quoted 10 lines · Patrick McHardy
Quoted 10 lines
net/netlink/af_netlink.c +2
-1-static int netlink_alloc_groups (struct sock *sk) +static int netlink_realloc_groups (struct sock *sk) {struct netlink_sock *nlk =nlk_sk (sk);unsigned int groups; +unsigned long *new_groups;int err =0 ;
Quoted 5 lines
Quoted 1 line
netlink_lock_table();This is actually a bug in the current code I think,
netlink_lock_tableis a reader lock.
Looks like, changed to netlink_table_grab()
Quoted 5 lines
Quoted 1 line
+int
netlink_change_ngroups(int unit, unsigned int groups)I think it would be more consistent to pass the kernel socket instead of the unit.
Alright, changed. Also added kernel doc for the function.
Quoted 5 lines
This might set the group to a value < 32. I don't expect it matters, but when I changed to old code to support > 32 groups I enforced a minimum of 32 so anything outside the kernel multicasting on them would still work (even though its a really stupid idea). So for consistency this should probably also use a minimum of 32.
Huh ok. Fixed, and added to documentation.
johannes
PATCH 2/3 netlink: allow removing multicast groups
In reply to Johannes BergAllow kicking listeners out of a multicast group when necessary (for example if that group is going to be removed.)
--- include/linux/netlink.h | 1 + net/netlink/af_netlink.c | 47 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 13 deletions(-)
include/linux/netlink.h +1 -0
@@ -162,6 +162,7 @@ extern struct sock *netlink_kernel_creatstruct mutex *cb_mutex, struct module *module);extern int netlink_change_ngroups (int unit,unsigned int groups); +extern void netlink_clear_multicast_users (int unit,unsigned int group);extern void netlink_ack (struct sk_buff *in_skb,struct nlmsghdr *nlh,int err);extern int netlink_has_listeners (struct sock *sk,unsigned int group);extern int netlink_unicast (struct sock *ssk,struct sk_buff *skb,__u32 pid,int nonblock);
net/netlink/af_netlink.c +34 -13
71 lines not on this page · raw message
Re: [patch 2/3] netlink: allow removing multicast groups
net/netlink/af_netlink.c void netlink_set_err(struct sock *ssk, u · line 1036
Quoted 7 lines · Johannes Berg
net/netlink/af_netlink.c +7
-0+static void netlink_update_socket_mc (struct netlink_sock *nlk, +unsigned int group, +int is_new) +{ +int old, new = !!is_new, subscriptions; + +netlink_table_grab ();
Having the caller lock the table would save lots of atomic operation in case of netlink_clear_multicast_users.
net/netlink/af_netlink.c void netlink_set_err(struct sock *ssk, u
Quoted 13 lines
net/netlink/af_netlink.c +12
-0+ old =test_bit (group -1 , nlk->groups); + subscriptions = nlk->subscriptions - old + new; +if (new) +__set_bit (group -1 , nlk->groups); +else +__clear_bit (group -1 , nlk->groups); +netlink_update_subscriptions (&nlk->sk, subscriptions); +netlink_update_listeners (&nlk->sk); +netlink_table_ungrab (); +} + +void netlink_clear_multicast_users (int unit,unsigned int group)
Same as in the last patch, passing the kernel socket would be nicer IMO.
net/netlink/af_netlink.c int netlink_change_ngroups(int unit, uns · line 1387
Quoted 5 lines
net/netlink/af_netlink.c +5
-0+{ +struct sock *sk; +struct hlist_node *node; + +read_lock (&nl_table_lock);
Won't this deadlock? netlink_table_grab takes a write-lock.
Quoted 12 lines
net/netlink/af_netlink.c +8
-0+ +sk_for_each_bound (sk, node, &nl_table[unit].mc_list) +netlink_update_socket_mc (nlk_sk (sk), group,0 ); + +read_unlock (&nl_table_lock); +} +EXPORT_SYMBOL (netlink_clear_multicast_users); +void netlink_set_nonroot (int protocol,unsigned int flags) {if ((unsigned int )protocol <MAX_LINKS )
Re: [patch 2/3] netlink: allow removing multicast groups
Quoted 2 lines · Patrick McHardy
Having the caller lock the table would save lots of atomic operation in case of
netlink_clear_multicast_users.
Good point.
Quoted 3 lines
Quoted 1 line
+void
netlink_clear_multicast_users(int unit, unsigned int group)Same as in the last patch, passing the kernel socket would be nicer IMO.
Changed.
Quoted 3 lines
net/netlink/af_netlink.c int netlink_change_ngroups(int unit, uns · line 1387
Quoted 1 line
net/netlink/af_netlink.c +1
-0+read_lock (&nl_table_lock);Won't this deadlock?
netlink_table_grabtakes a write-lock.
I guess it's valid to update a read lock to a write lock? Or I was just lucky on UP. But moving the lock out of netlink_clear_multicast_users() made this obvious and I just use the write lock now.
johannes
PATCH 3/3 generic netlink: dynamic multicast groups
In reply to Johannes BergIntroduce API to dynamically register and unregister multicast groups.
--- include/linux/genetlink.h | 13 +++ include/net/genetlink.h | 22 +++++ net/netlink/genetlink.c | 190 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 218 insertions(+), 7 deletions(-)
include/net/genetlink.h +22 -0
@@ -5,6 +5,22 @@#include <net/netlink.h> /** +* struct genl_multicast_group - generic netlink multicast group +* @name: name of the multicast group, names are per-family +* @id: multicast group ID, assigned by the core, to use with +* genlmsg_multicast(). +* @list: list entry for linking +* @family: pointer to family, need not be set before registering +*/ +struct genl_multicast_group +{ +struct genl_family *family;/* private */ +struct list_head list;/* private */ +char name[GENL_NAMSIZ ]; +u32 id; +}; + +/** * struct genl_family - generic netlink family * @id: protocol family idenfitier * @hdrsize: length of user specific header in bytes
@@ -14,6 +30,7 @@* @attrbuf: buffer to store parsed attributes * @ops_list: list of all assigned operations * @family_list: family list +* @mcast_groups: multicast groups list */ struct genl_family {
@@ -25,6 +42,7 @@ struct genl_familystruct nlattr ** attrbuf;/* private */ struct list_head ops_list;/* private */ struct list_head family_list;/* private */ +struct list_head mcast_groups;/* private */ };/**
@@ -73,6 +91,10 @@ extern int genl_register_family(struct gextern int genl_unregister_family (struct genl_family *family);extern int genl_register_ops (struct genl_family *,struct genl_ops *ops);extern int genl_unregister_ops (struct genl_family *,struct genl_ops *ops); +extern int genl_register_mc_group (struct genl_family *family, +struct genl_multicast_group *grp); +extern void genl_unregister_mc_group (struct genl_family *family, +struct genl_multicast_group *grp);extern struct sock *genl_sock;
net/netlink/genetlink.c +183 -7
262 lines not on this page · raw message
include/linux/genetlink.h +13 -0
@@ -39,6 +39,9 @@ enum {CTRL_CMD_NEWOPS ,CTRL_CMD_DELOPS ,CTRL_CMD_GETOPS , +CTRL_CMD_NEWMCAST_GRP , +CTRL_CMD_DELMCAST_GRP , +CTRL_CMD_GETMCAST_GRP ,/* unused */ __CTRL_CMD_MAX, };
@@ -52,6 +55,7 @@ enum {CTRL_ATTR_HDRSIZE ,CTRL_ATTR_MAXATTR ,CTRL_ATTR_OPS , +CTRL_ATTR_MCAST_GROUPS , __CTRL_ATTR_MAX, };
@@ -66,4 +70,13 @@ enum {#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1) +enum { +CTRL_ATTR_MCAST_GRP_UNSPEC , +CTRL_ATTR_MCAST_GRP_NAME , +CTRL_ATTR_MCAST_GRP_ID , + __CTRL_ATTR_MCAST_GRP_MAX, +}; + +#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1) +#endif /* __LINUX_GENERIC_NETLINK_H */
PATCH v2 1/3 netlink: allocate group bitmaps dynamically
In reply to Johannes BergAllow changing the number of groups for a netlink family after it has been created, use RCU to protect the listeners bitmap keeping netlink_has_listeners() lock-free.
---
Changes: incorporate Patrick's comments, add kernel-doc
include/linux/netlink.h | 1 net/netlink/af_netlink.c | 106 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 83 insertions(+), 24 deletions(-)
net/netlink/af_netlink.c +82 -24
@@ -62,6 +62,7 @@#include <net/netlink.h> #define NLGRPSZ (x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) +#define NLGRPLONGS (x) (NLGRPSZ(x)/sizeof(unsigned long))struct netlink_sock {/* struct sock has to be the first member of netlink_sock */
@@ -314,10 +315,12 @@ netlink_update_listeners(struct sock *skunsigned long mask;unsigned int i; -for (i =0 ; i <NLGRPSZ (tbl->groups)/sizeof (unsigned long ); i++) { +for (i =0 ; i <NLGRPLONGS (tbl->groups); i++) { mask =0 ; -sk_for_each_bound (sk, node, &tbl->mc_list) - mask |=nlk_sk (sk)->groups[i]; +sk_for_each_bound (sk, node, &tbl->mc_list) { +if (i <NLGRPLONGS (nlk_sk (sk)->ngroups)) + mask |=nlk_sk (sk)->groups[i]; + } tbl->listeners[i] = mask; }/* this function is only called with the netlink table "grabbed", which
@@ -555,26 +558,37 @@ netlink_update_subscriptions(struct sock nlk->subscriptions = subscriptions; } -static int netlink_alloc_groups (struct sock *sk) +static int netlink_realloc_groups (struct sock *sk) {struct netlink_sock *nlk =nlk_sk (sk);unsigned int groups; +unsigned long *new_groups;int err =0 ; -netlink_lock_table (); +netlink_table_grab (); + groups = nl_table[sk->sk_protocol].groups; -if (!nl_table[sk->sk_protocol].registered) +if (!nl_table[sk->sk_protocol].registered) { err = -ENOENT ; -netlink_unlock_table (); + goto out_unlock; + } -if (err) -return err; +if (nlk->ngroups >= groups) + goto out_unlock; - nlk->groups =kzalloc (NLGRPSZ (groups),GFP_KERNEL ); -if (nlk->groups ==NULL ) -return -ENOMEM ; + new_groups =krealloc (nlk->groups,NLGRPSZ (groups),GFP_ATOMIC ); +if (new_groups ==NULL ) { + err = -ENOMEM ; + goto out_unlock; + } +memset ((char *)new_groups +NLGRPSZ (nlk->ngroups),0 , +NLGRPSZ (groups) -NLGRPSZ (nlk->ngroups)); + + nlk->groups = new_groups; nlk->ngroups = groups; -return 0 ; + out_unlock: +netlink_table_ungrab (); +return err; }static int netlink_bind (struct socket *sock,struct sockaddr *addr,int addr_len)
@@ -591,11 +605,9 @@ static int netlink_bind(struct socket *sif (nladdr->nl_groups) {if (!netlink_capable (sock,NL_NONROOT_RECV ))return -EPERM ; -if (nlk->groups ==NULL ) { - err =netlink_alloc_groups (sk); -if (err) -return err; - } + err =netlink_realloc_groups (sk); +if (err) +return err; }if (nlk->pid) {
@@ -839,10 +851,18 @@ retry:int netlink_has_listeners (struct sock *sk,unsigned int group) {int res =0 ; +unsigned long *listeners;BUG_ON (!(nlk_sk (sk)->flags &NETLINK_KERNEL_SOCKET )); + +rcu_read_lock (); + listeners =rcu_dereference (nl_table[sk->sk_protocol].listeners); +if (group -1 < nl_table[sk->sk_protocol].groups) - res =test_bit (group -1 , nl_table[sk->sk_protocol].listeners); + res =test_bit (group -1 , listeners); + +rcu_read_unlock (); +return res; }EXPORT_SYMBOL_GPL (netlink_has_listeners);
@@ -1037,11 +1057,9 @@ static int netlink_setsockopt(struct socif (!netlink_capable (sock,NL_NONROOT_RECV ))return -EPERM ; -if (nlk->groups ==NULL ) { - err =netlink_alloc_groups (sk); -if (err) -return err; - } + err =netlink_realloc_groups (sk); +if (err) +return err;if (!val || val -1 >= nlk->ngroups)return -EINVAL ;netlink_table_grab ();
@@ -1328,6 +1346,46 @@ out_sock_release:return NULL ; } +/** +* netlink_change_ngroups - change number of multicast groups +* +* This changes the number of multicast groups that are available +* on a certain netlink family. Note that it is not possible to +* change the number of groups to below 32. +* +* @sk: The kernel netlink socket, as returned by netlink_kernel_create(). +* @groups: The new number of groups. +*/ +int netlink_change_ngroups (struct sock *sk,unsigned int groups) +{ +unsigned long *listeners, *old =NULL ; +struct netlink_table *tbl = &nl_table[sk->sk_protocol]; +int err =0 ; + +if (groups <32 ) + groups =32 ; + +netlink_table_grab (); +if (NLGRPSZ (tbl->groups) <NLGRPSZ (groups)) { + listeners =kzalloc (NLGRPSZ (groups),GFP_ATOMIC ); +if (!listeners) { + err = -ENOMEM ; + goto out_ungrab; + } + old = tbl->listeners; +memcpy (listeners, old,NLGRPSZ (tbl->groups)); +rcu_assign_pointer (tbl->listeners, listeners); + } + tbl->groups = groups; + + out_ungrab: +netlink_table_ungrab (); +synchronize_rcu (); +kfree (old); +return err; +} +EXPORT_SYMBOL (netlink_change_ngroups); +void netlink_set_nonroot (int protocol,unsigned int flags) {if ((unsigned int )protocol <MAX_LINKS )
include/linux/netlink.h +1 -0
@@ -161,6 +161,7 @@ extern struct sock *netlink_kernel_creatvoid (*input)(struct sock *sk,int len), struct mutex *cb_mutex, struct module *module); +extern int netlink_change_ngroups (struct sock *sk,unsigned int groups);extern void netlink_ack (struct sk_buff *in_skb,struct nlmsghdr *nlh,int err);extern int netlink_has_listeners (struct sock *sk,unsigned int group);extern int netlink_unicast (struct sock *ssk,struct sk_buff *skb,__u32 pid,int nonblock);
Re: [PATCH v2 1/3] netlink: allocate group bitmaps dynamically
Quoted 8 lines · Johannes Berg
Allow changing the number of groups for a netlink family after it has been created, use RCU to protect the listeners bitmap keeping
netlink_has_listeners()lock-free.Signed-off-by Johannes Berg <[email protected]>---
Changes: incorporate Patrick's comments, add kernel-doc
All three patches look good to me.
and for Jamal again ..
David Miller
maintainerRe: [PATCH v2 1/3] netlink: allocate group bitmaps dynamically
From: Patrick McHardy <[email protected]>
Date: Wed, 18 Jul 2007 18:30:04 +0200
Quoted 11 lines
Quoted 8 lines · Johannes Berg
Allow changing the number of groups for a netlink family after it has been created, use RCU to protect the listeners bitmap keeping
netlink_has_listeners()lock-free.Signed-off-by Johannes Berg <[email protected]>---
Changes: incorporate Patrick's comments, add kernel-doc
Quoted 7 lines
All three patches look good to me.
Acked-by Patrick McHardy <[email protected]>and for Jamal again ..
Acked-by Jamal Hadi Salim <[email protected]>
Aha, Johannes did resubmit all 3 patches, they arrived out of order here which confused me :-)
I'll apply these, thanks.
Re: [PATCH v2 1/3] netlink: allocate group bitmaps dynamically
Quoted 4 lines · David Miller
Quoted 4 lines
All three patches look good to me.
Acked-by Patrick McHardy <[email protected]>
Quoted 8 lines
Quoted 3 lines
and for Jamal again ..
Acked-by Jamal Hadi Salim <[email protected]>Aha, Johannes did resubmit all 3 patches, they arrived out of order here which confused me :-)
I'll apply these, thanks.
Thanks. And sorry about the out-of-order, my mistake because I'd noticed a small bug in one patch and didn't rewrite all three emails.
johannes
PATCH v2 2/3 netlink: allow removing multicast groups
In reply to Johannes BergAllow kicking listeners out of a multicast group when necessary (for example if that group is going to be removed.)
---
Changes: incorporate Patrick's comments, add kernel-doc.
include/linux/netlink.h | 1 net/netlink/af_netlink.c | 57 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 12 deletions(-)
include/linux/netlink.h +1 -0
@@ -162,6 +162,7 @@ extern struct sock *netlink_kernel_creatstruct mutex *cb_mutex, struct module *module);extern int netlink_change_ngroups (struct sock *sk,unsigned int groups); +extern void netlink_clear_multicast_users (struct sock *sk,unsigned int group);extern void netlink_ack (struct sk_buff *in_skb,struct nlmsghdr *nlh,int err);extern int netlink_has_listeners (struct sock *sk,unsigned int group);extern int netlink_unicast (struct sock *ssk,struct sk_buff *skb,__u32 pid,int nonblock);
net/netlink/af_netlink.c +45 -12
87 lines not on this page · raw message
David Miller
maintainerRe: [PATCH v2 2/3] netlink: allow removing multicast groups
Please don't resubmit sub-patches, I delete entire patch series from my inbox when some of them need revisions.
Please resubmit the whole set once everything is worked out.
Thanks.
PATCH v2 3/3 generic netlink: dynamic multicast groups
In reply to Johannes BergIntroduce API to dynamically register and unregister multicast groups.
---
Changes: update for slightly changed API from v2 of patch 1 and 2, add kernel-doc, properly register the generic netlink group as well, fix bug with that group (it isn't ID 1 but ID 0x10)
include/linux/genetlink.h | 13 ++ include/net/genetlink.h | 22 ++++ net/netlink/genetlink.c | 235 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 263 insertions(+), 7 deletions(-)
include/net/genetlink.h +22 -0
@@ -5,6 +5,22 @@#include <net/netlink.h> /** +* struct genl_multicast_group - generic netlink multicast group +* @name: name of the multicast group, names are per-family +* @id: multicast group ID, assigned by the core, to use with +* genlmsg_multicast(). +* @list: list entry for linking +* @family: pointer to family, need not be set before registering +*/ +struct genl_multicast_group +{ +struct genl_family *family;/* private */ +struct list_head list;/* private */ +char name[GENL_NAMSIZ ]; +u32 id; +}; + +/** * struct genl_family - generic netlink family * @id: protocol family idenfitier * @hdrsize: length of user specific header in bytes
@@ -14,6 +30,7 @@* @attrbuf: buffer to store parsed attributes * @ops_list: list of all assigned operations * @family_list: family list +* @mcast_groups: multicast groups list */ struct genl_family {
@@ -25,6 +42,7 @@ struct genl_familystruct nlattr ** attrbuf;/* private */ struct list_head ops_list;/* private */ struct list_head family_list;/* private */ +struct list_head mcast_groups;/* private */ };/**
@@ -73,6 +91,10 @@ extern int genl_register_family(struct gextern int genl_unregister_family (struct genl_family *family);extern int genl_register_ops (struct genl_family *,struct genl_ops *ops);extern int genl_unregister_ops (struct genl_family *,struct genl_ops *ops); +extern int genl_register_mc_group (struct genl_family *family, +struct genl_multicast_group *grp); +extern void genl_unregister_mc_group (struct genl_family *family, +struct genl_multicast_group *grp);extern struct sock *genl_sock;
net/netlink/genetlink.c +228 -7
316 lines not on this page · raw message
include/linux/genetlink.h +13 -0
@@ -39,6 +39,9 @@ enum {CTRL_CMD_NEWOPS ,CTRL_CMD_DELOPS ,CTRL_CMD_GETOPS , +CTRL_CMD_NEWMCAST_GRP , +CTRL_CMD_DELMCAST_GRP , +CTRL_CMD_GETMCAST_GRP ,/* unused */ __CTRL_CMD_MAX, };
@@ -52,6 +55,7 @@ enum {CTRL_ATTR_HDRSIZE ,CTRL_ATTR_MAXATTR ,CTRL_ATTR_OPS , +CTRL_ATTR_MCAST_GROUPS , __CTRL_ATTR_MAX, };
@@ -66,4 +70,13 @@ enum {#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1) +enum { +CTRL_ATTR_MCAST_GRP_UNSPEC , +CTRL_ATTR_MCAST_GRP_NAME , +CTRL_ATTR_MCAST_GRP_ID , + __CTRL_ATTR_MCAST_GRP_MAX, +}; + +#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1) +#endif /* __LINUX_GENERIC_NETLINK_H */
Oh, this patchset triggers a current bug in slub, see:
http://article.gmane.org/gmane.linux.kernel/556887
I forgot mentioning that yesterday, I hope it's not causing any trouble. Also, I had expected it to be fixed soonish, but can't see that it is.
johannes