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>
This commit is contained in:
parent
d91824c08f
commit
f84f771d94
3 changed files with 30 additions and 24 deletions
|
@ -52,14 +52,14 @@ struct genl_family {
|
||||||
unsigned int maxattr;
|
unsigned int maxattr;
|
||||||
bool netnsok;
|
bool netnsok;
|
||||||
bool parallel_ops;
|
bool parallel_ops;
|
||||||
int (*pre_doit)(struct genl_ops *ops,
|
int (*pre_doit)(const struct genl_ops *ops,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
struct genl_info *info);
|
struct genl_info *info);
|
||||||
void (*post_doit)(struct genl_ops *ops,
|
void (*post_doit)(const struct genl_ops *ops,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
struct genl_info *info);
|
struct genl_info *info);
|
||||||
struct nlattr ** attrbuf; /* private */
|
struct nlattr ** attrbuf; /* private */
|
||||||
struct genl_ops * ops; /* private */
|
const struct genl_ops * ops; /* private */
|
||||||
unsigned int n_ops; /* private */
|
unsigned int n_ops; /* private */
|
||||||
struct list_head family_list; /* private */
|
struct list_head family_list; /* private */
|
||||||
struct list_head mcast_groups; /* private */
|
struct list_head mcast_groups; /* private */
|
||||||
|
@ -132,10 +132,10 @@ static inline int genl_register_family(struct genl_family *family)
|
||||||
}
|
}
|
||||||
|
|
||||||
int __genl_register_family_with_ops(struct genl_family *family,
|
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,
|
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;
|
family->module = THIS_MODULE;
|
||||||
return __genl_register_family_with_ops(family, ops, n_ops);
|
return __genl_register_family_with_ops(family, ops, n_ops);
|
||||||
|
|
|
@ -106,7 +106,7 @@ static struct genl_family *genl_family_find_byname(char *name)
|
||||||
return NULL;
|
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;
|
int i;
|
||||||
|
|
||||||
|
@ -283,7 +283,8 @@ static void genl_unregister_mc_groups(struct genl_family *family)
|
||||||
__genl_unregister_mc_group(family, grp);
|
__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)
|
unsigned int n_ops)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -294,12 +295,6 @@ static int genl_validate_add_ops(struct genl_family *family, struct genl_ops *op
|
||||||
for (j = i + 1; j < n_ops; j++)
|
for (j = i + 1; j < n_ops; j++)
|
||||||
if (ops[i].cmd == ops[j].cmd)
|
if (ops[i].cmd == ops[j].cmd)
|
||||||
return -EINVAL;
|
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 */
|
/* family is not registered yet, so no locking needed */
|
||||||
|
@ -399,7 +394,7 @@ EXPORT_SYMBOL(__genl_register_family);
|
||||||
* Return 0 on success or a negative error code.
|
* Return 0 on success or a negative error code.
|
||||||
*/
|
*/
|
||||||
int __genl_register_family_with_ops(struct genl_family *family,
|
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;
|
int err;
|
||||||
|
|
||||||
|
@ -479,7 +474,8 @@ EXPORT_SYMBOL(genlmsg_put);
|
||||||
|
|
||||||
static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
|
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;
|
int rc;
|
||||||
|
|
||||||
genl_lock();
|
genl_lock();
|
||||||
|
@ -490,7 +486,8 @@ static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
|
||||||
|
|
||||||
static int genl_lock_done(struct netlink_callback *cb)
|
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;
|
int rc = 0;
|
||||||
|
|
||||||
if (ops->done) {
|
if (ops->done) {
|
||||||
|
@ -505,7 +502,7 @@ static int genl_family_rcv_msg(struct genl_family *family,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
struct nlmsghdr *nlh)
|
struct nlmsghdr *nlh)
|
||||||
{
|
{
|
||||||
struct genl_ops *ops;
|
const struct genl_ops *ops;
|
||||||
struct net *net = sock_net(skb->sk);
|
struct net *net = sock_net(skb->sk);
|
||||||
struct genl_info info;
|
struct genl_info info;
|
||||||
struct genlmsghdr *hdr = nlmsg_data(nlh);
|
struct genlmsghdr *hdr = nlmsg_data(nlh);
|
||||||
|
@ -537,7 +534,8 @@ static int genl_family_rcv_msg(struct genl_family *family,
|
||||||
if (!family->parallel_ops) {
|
if (!family->parallel_ops) {
|
||||||
struct netlink_dump_control c = {
|
struct netlink_dump_control c = {
|
||||||
.module = family->module,
|
.module = family->module,
|
||||||
.data = ops,
|
/* we have const, but the netlink API doesn't */
|
||||||
|
.data = (void *)ops,
|
||||||
.dump = genl_lock_dumpit,
|
.dump = genl_lock_dumpit,
|
||||||
.done = genl_lock_done,
|
.done = genl_lock_done,
|
||||||
};
|
};
|
||||||
|
@ -669,14 +667,22 @@ static int ctrl_fill_info(struct genl_family *family, u32 portid, u32 seq,
|
||||||
|
|
||||||
for (i = 0; i < family->n_ops; i++) {
|
for (i = 0; i < family->n_ops; i++) {
|
||||||
struct nlattr *nest;
|
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);
|
nest = nla_nest_start(skb, i + 1);
|
||||||
if (nest == NULL)
|
if (nest == NULL)
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
if (nla_put_u32(skb, CTRL_ATTR_OP_ID, ops->cmd) ||
|
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;
|
goto nla_put_failure;
|
||||||
|
|
||||||
nla_nest_end(skb, nest);
|
nla_nest_end(skb, nest);
|
||||||
|
|
|
@ -30,9 +30,9 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
|
||||||
struct cfg80211_crypto_settings *settings,
|
struct cfg80211_crypto_settings *settings,
|
||||||
int cipher_limit);
|
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);
|
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);
|
struct genl_info *info);
|
||||||
|
|
||||||
/* the netlink family */
|
/* the netlink family */
|
||||||
|
@ -8851,7 +8851,7 @@ static int nl80211_crit_protocol_stop(struct sk_buff *skb,
|
||||||
#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
|
#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
|
||||||
NL80211_FLAG_CHECK_NETDEV_UP)
|
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 genl_info *info)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev;
|
struct cfg80211_registered_device *rdev;
|
||||||
|
@ -8920,7 +8920,7 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
|
||||||
return 0;
|
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)
|
struct genl_info *info)
|
||||||
{
|
{
|
||||||
if (info->user_ptr[1]) {
|
if (info->user_ptr[1]) {
|
||||||
|
|
Loading…
Reference in a new issue