Commit 2ae0f17d authored by Johannes Berg's avatar Johannes Berg Committed by David S. Miller

genetlink: use idr to track families

Since generic netlink family IDs are small integers, allocated
densely, IDR is an ideal match for lookups. Replace the existing
hand-written hash-table with IDR for allocation and lookup.

This lets the families only be written to once, during register,
since the list_head can be removed and removal of a family won't
cause any writes.

It also slightly reduces the code size (by about 1.3k on x86-64).
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 489111e5
...@@ -40,7 +40,6 @@ struct genl_info; ...@@ -40,7 +40,6 @@ struct genl_info;
* generic netlink family is removed while there are still open * generic netlink family is removed while there are still open
* sockets. * sockets.
* @attrbuf: buffer to store parsed attributes (private) * @attrbuf: buffer to store parsed attributes (private)
* @family_list: family list (private)
* @mcgrps: multicast groups used by this family * @mcgrps: multicast groups used by this family
* @n_mcgrps: number of multicast groups * @n_mcgrps: number of multicast groups
* @mcgrp_offset: starting number of multicast group IDs in this family * @mcgrp_offset: starting number of multicast group IDs in this family
...@@ -70,11 +69,10 @@ struct genl_family { ...@@ -70,11 +69,10 @@ struct genl_family {
unsigned int n_ops; unsigned int n_ops;
unsigned int n_mcgrps; unsigned int n_mcgrps;
unsigned int mcgrp_offset; /* private */ unsigned int mcgrp_offset; /* private */
struct list_head family_list; /* private */
struct module *module; struct module *module;
}; };
struct nlattr **genl_family_attrbuf(struct genl_family *family); struct nlattr **genl_family_attrbuf(const struct genl_family *family);
/** /**
* struct genl_info - receiving information * struct genl_info - receiving information
...@@ -134,12 +132,12 @@ struct genl_ops { ...@@ -134,12 +132,12 @@ struct genl_ops {
}; };
int genl_register_family(struct genl_family *family); int genl_register_family(struct genl_family *family);
int genl_unregister_family(struct genl_family *family); int genl_unregister_family(const struct genl_family *family);
void genl_notify(struct genl_family *family, struct sk_buff *skb, void genl_notify(const struct genl_family *family, struct sk_buff *skb,
struct genl_info *info, u32 group, gfp_t flags); struct genl_info *info, u32 group, gfp_t flags);
void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
struct genl_family *family, int flags, u8 cmd); const struct genl_family *family, int flags, u8 cmd);
/** /**
* genlmsg_nlhdr - Obtain netlink header from user specified header * genlmsg_nlhdr - Obtain netlink header from user specified header
...@@ -148,8 +146,8 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, ...@@ -148,8 +146,8 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
* *
* Returns pointer to netlink header. * Returns pointer to netlink header.
*/ */
static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr, static inline struct nlmsghdr *
struct genl_family *family) genlmsg_nlhdr(void *user_hdr, const struct genl_family *family)
{ {
return (struct nlmsghdr *)((char *)user_hdr - return (struct nlmsghdr *)((char *)user_hdr -
family->hdrsize - family->hdrsize -
...@@ -185,7 +183,7 @@ static inline int genlmsg_parse(const struct nlmsghdr *nlh, ...@@ -185,7 +183,7 @@ static inline int genlmsg_parse(const struct nlmsghdr *nlh,
*/ */
static inline void genl_dump_check_consistent(struct netlink_callback *cb, static inline void genl_dump_check_consistent(struct netlink_callback *cb,
void *user_hdr, void *user_hdr,
struct genl_family *family) const struct genl_family *family)
{ {
nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr, family)); nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr, family));
} }
...@@ -202,7 +200,7 @@ static inline void genl_dump_check_consistent(struct netlink_callback *cb, ...@@ -202,7 +200,7 @@ static inline void genl_dump_check_consistent(struct netlink_callback *cb,
*/ */
static inline void *genlmsg_put_reply(struct sk_buff *skb, static inline void *genlmsg_put_reply(struct sk_buff *skb,
struct genl_info *info, struct genl_info *info,
struct genl_family *family, const struct genl_family *family,
int flags, u8 cmd) int flags, u8 cmd)
{ {
return genlmsg_put(skb, info->snd_portid, info->snd_seq, family, return genlmsg_put(skb, info->snd_portid, info->snd_seq, family,
...@@ -239,7 +237,7 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr) ...@@ -239,7 +237,7 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
* @group: offset of multicast group in groups array * @group: offset of multicast group in groups array
* @flags: allocation flags * @flags: allocation flags
*/ */
static inline int genlmsg_multicast_netns(struct genl_family *family, static inline int genlmsg_multicast_netns(const struct genl_family *family,
struct net *net, struct sk_buff *skb, struct net *net, struct sk_buff *skb,
u32 portid, unsigned int group, gfp_t flags) u32 portid, unsigned int group, gfp_t flags)
{ {
...@@ -257,7 +255,7 @@ static inline int genlmsg_multicast_netns(struct genl_family *family, ...@@ -257,7 +255,7 @@ static inline int genlmsg_multicast_netns(struct genl_family *family,
* @group: offset of multicast group in groups array * @group: offset of multicast group in groups array
* @flags: allocation flags * @flags: allocation flags
*/ */
static inline int genlmsg_multicast(struct genl_family *family, static inline int genlmsg_multicast(const struct genl_family *family,
struct sk_buff *skb, u32 portid, struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags) unsigned int group, gfp_t flags)
{ {
...@@ -275,7 +273,7 @@ static inline int genlmsg_multicast(struct genl_family *family, ...@@ -275,7 +273,7 @@ static inline int genlmsg_multicast(struct genl_family *family,
* *
* This function must hold the RTNL or rcu_read_lock(). * This function must hold the RTNL or rcu_read_lock().
*/ */
int genlmsg_multicast_allns(struct genl_family *family, int genlmsg_multicast_allns(const struct genl_family *family,
struct sk_buff *skb, u32 portid, struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags); unsigned int group, gfp_t flags);
...@@ -359,8 +357,9 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags) ...@@ -359,8 +357,9 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
* This function returns the number of broadcast listeners that have set the * This function returns the number of broadcast listeners that have set the
* NETLINK_RECV_NO_ENOBUFS socket option. * NETLINK_RECV_NO_ENOBUFS socket option.
*/ */
static inline int genl_set_err(struct genl_family *family, struct net *net, static inline int genl_set_err(const struct genl_family *family,
u32 portid, u32 group, int code) struct net *net, u32 portid,
u32 group, int code)
{ {
if (WARN_ON_ONCE(group >= family->n_mcgrps)) if (WARN_ON_ONCE(group >= family->n_mcgrps))
return -EINVAL; return -EINVAL;
...@@ -368,7 +367,7 @@ static inline int genl_set_err(struct genl_family *family, struct net *net, ...@@ -368,7 +367,7 @@ static inline int genl_set_err(struct genl_family *family, struct net *net,
return netlink_set_err(net->genl_sock, portid, group, code); return netlink_set_err(net->genl_sock, portid, group, code);
} }
static inline int genl_has_listeners(struct genl_family *family, static inline int genl_has_listeners(const struct genl_family *family,
struct net *net, unsigned int group) struct net *net, unsigned int group)
{ {
if (WARN_ON_ONCE(group >= family->n_mcgrps)) if (WARN_ON_ONCE(group >= family->n_mcgrps))
......
...@@ -29,6 +29,8 @@ struct genlmsghdr { ...@@ -29,6 +29,8 @@ struct genlmsghdr {
#define GENL_ID_CTRL NLMSG_MIN_TYPE #define GENL_ID_CTRL NLMSG_MIN_TYPE
#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1) #define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1)
#define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2) #define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2)
/* must be last reserved + 1 */
#define GENL_START_ALLOC (NLMSG_MIN_TYPE + 3)
/************************************************************************** /**************************************************************************
* Controller * Controller
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment