genetlink: allow making ops const
Allow making the ops array const by not modifying the ops
flags on registration but rather only when ops are sent
out in the family information.
No users are updated yet except for the pre_doit/post_doit
calls in wireless (the only ones that exist now.)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index d4802af..d87486a 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -52,14 +52,14 @@
unsigned int maxattr;
bool netnsok;
bool parallel_ops;
- int (*pre_doit)(struct genl_ops *ops,
+ int (*pre_doit)(const struct genl_ops *ops,
struct sk_buff *skb,
struct genl_info *info);
- void (*post_doit)(struct genl_ops *ops,
+ void (*post_doit)(const struct genl_ops *ops,
struct sk_buff *skb,
struct genl_info *info);
struct nlattr ** attrbuf; /* private */
- struct genl_ops * ops; /* private */
+ const struct genl_ops * ops; /* private */
unsigned int n_ops; /* private */
struct list_head family_list; /* private */
struct list_head mcast_groups; /* private */
@@ -132,10 +132,10 @@
}
int __genl_register_family_with_ops(struct genl_family *family,
- struct genl_ops *ops, size_t n_ops);
+ const struct genl_ops *ops, size_t n_ops);
static inline int genl_register_family_with_ops(struct genl_family *family,
- struct genl_ops *ops, size_t n_ops)
+ const struct genl_ops *ops, size_t n_ops)
{
family->module = THIS_MODULE;
return __genl_register_family_with_ops(family, ops, n_ops);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index d8273b0..a7c62d3 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -106,7 +106,7 @@
return NULL;
}
-static struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family)
+static const struct genl_ops *genl_get_cmd(u8 cmd, struct genl_family *family)
{
int i;
@@ -283,7 +283,8 @@
__genl_unregister_mc_group(family, grp);
}
-static int genl_validate_add_ops(struct genl_family *family, struct genl_ops *ops,
+static int genl_validate_add_ops(struct genl_family *family,
+ const struct genl_ops *ops,
unsigned int n_ops)
{
int i, j;
@@ -294,12 +295,6 @@
for (j = i + 1; j < n_ops; j++)
if (ops[i].cmd == ops[j].cmd)
return -EINVAL;
- if (ops[i].dumpit)
- ops[i].flags |= GENL_CMD_CAP_DUMP;
- if (ops[i].doit)
- ops[i].flags |= GENL_CMD_CAP_DO;
- if (ops[i].policy)
- ops[i].flags |= GENL_CMD_CAP_HASPOL;
}
/* family is not registered yet, so no locking needed */
@@ -399,7 +394,7 @@
* Return 0 on success or a negative error code.
*/
int __genl_register_family_with_ops(struct genl_family *family,
- struct genl_ops *ops, size_t n_ops)
+ const struct genl_ops *ops, size_t n_ops)
{
int err;
@@ -479,7 +474,8 @@
static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct genl_ops *ops = cb->data;
+ /* our ops are always const - netlink API doesn't propagate that */
+ const struct genl_ops *ops = cb->data;
int rc;
genl_lock();
@@ -490,7 +486,8 @@
static int genl_lock_done(struct netlink_callback *cb)
{
- struct genl_ops *ops = cb->data;
+ /* our ops are always const - netlink API doesn't propagate that */
+ const struct genl_ops *ops = cb->data;
int rc = 0;
if (ops->done) {
@@ -505,7 +502,7 @@
struct sk_buff *skb,
struct nlmsghdr *nlh)
{
- struct genl_ops *ops;
+ const struct genl_ops *ops;
struct net *net = sock_net(skb->sk);
struct genl_info info;
struct genlmsghdr *hdr = nlmsg_data(nlh);
@@ -537,7 +534,8 @@
if (!family->parallel_ops) {
struct netlink_dump_control c = {
.module = family->module,
- .data = ops,
+ /* we have const, but the netlink API doesn't */
+ .data = (void *)ops,
.dump = genl_lock_dumpit,
.done = genl_lock_done,
};
@@ -669,14 +667,22 @@
for (i = 0; i < family->n_ops; i++) {
struct nlattr *nest;
- struct genl_ops *ops = &family->ops[i];
+ const struct genl_ops *ops = &family->ops[i];
+ u32 flags = ops->flags;
+
+ if (ops->dumpit)
+ flags |= GENL_CMD_CAP_DUMP;
+ if (ops->doit)
+ flags |= GENL_CMD_CAP_DO;
+ if (ops->policy)
+ flags |= GENL_CMD_CAP_HASPOL;
nest = nla_nest_start(skb, i + 1);
if (nest == NULL)
goto nla_put_failure;
if (nla_put_u32(skb, CTRL_ATTR_OP_ID, ops->cmd) ||
- nla_put_u32(skb, CTRL_ATTR_OP_FLAGS, ops->flags))
+ nla_put_u32(skb, CTRL_ATTR_OP_FLAGS, flags))
goto nla_put_failure;
nla_nest_end(skb, nest);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a7f4e79..3fef559 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -30,9 +30,9 @@
struct cfg80211_crypto_settings *settings,
int cipher_limit);
-static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
+static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info);
-static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
+static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info);
/* the netlink family */
@@ -8851,7 +8851,7 @@
#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
NL80211_FLAG_CHECK_NETDEV_UP)
-static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
+static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
{
struct cfg80211_registered_device *rdev;
@@ -8920,7 +8920,7 @@
return 0;
}
-static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
+static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
{
if (info->user_ptr[1]) {