Commit d32c3825 authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

devlink: Allow taking device lock in pre_doit operations

Introduce a new private flag ('DEVLINK_NL_FLAG_NEED_DEV_LOCK') to allow
netlink commands to specify that they need to acquire the device lock in
their pre_doit operation and release it in their post_doit operation.

The reload command will use this flag in the subsequent patch.

No functional changes intended.
Signed-off-by: default avatarIdo Schimmel <idosch@nvidia.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarPetr Machata <petrm@nvidia.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c8d0a7d6
...@@ -152,7 +152,8 @@ typedef int devlink_nl_dump_one_func_t(struct sk_buff *msg, ...@@ -152,7 +152,8 @@ typedef int devlink_nl_dump_one_func_t(struct sk_buff *msg,
int flags); int flags);
struct devlink * struct devlink *
devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs); devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs,
bool dev_lock);
int devlink_nl_dumpit(struct sk_buff *msg, struct netlink_callback *cb, int devlink_nl_dumpit(struct sk_buff *msg, struct netlink_callback *cb,
devlink_nl_dump_one_func_t *dump_one); devlink_nl_dump_one_func_t *dump_one);
......
...@@ -1151,7 +1151,8 @@ devlink_health_reporter_get_from_cb_lock(struct netlink_callback *cb) ...@@ -1151,7 +1151,8 @@ devlink_health_reporter_get_from_cb_lock(struct netlink_callback *cb)
struct nlattr **attrs = info->attrs; struct nlattr **attrs = info->attrs;
struct devlink *devlink; struct devlink *devlink;
devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs); devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs,
false);
if (IS_ERR(devlink)) if (IS_ERR(devlink))
return NULL; return NULL;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#define DEVLINK_NL_FLAG_NEED_PORT BIT(0) #define DEVLINK_NL_FLAG_NEED_PORT BIT(0)
#define DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT BIT(1) #define DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT BIT(1)
#define DEVLINK_NL_FLAG_NEED_DEV_LOCK BIT(2)
static const struct genl_multicast_group devlink_nl_mcgrps[] = { static const struct genl_multicast_group devlink_nl_mcgrps[] = {
[DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME }, [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
...@@ -64,7 +65,8 @@ int devlink_nl_msg_reply_and_new(struct sk_buff **msg, struct genl_info *info) ...@@ -64,7 +65,8 @@ int devlink_nl_msg_reply_and_new(struct sk_buff **msg, struct genl_info *info)
} }
struct devlink * struct devlink *
devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs) devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs,
bool dev_lock)
{ {
struct devlink *devlink; struct devlink *devlink;
unsigned long index; unsigned long index;
...@@ -78,12 +80,12 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs) ...@@ -78,12 +80,12 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs)
devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]); devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
devlinks_xa_for_each_registered_get(net, index, devlink) { devlinks_xa_for_each_registered_get(net, index, devlink) {
devl_lock(devlink); devl_dev_lock(devlink, dev_lock);
if (devl_is_registered(devlink) && if (devl_is_registered(devlink) &&
strcmp(devlink->dev->bus->name, busname) == 0 && strcmp(devlink->dev->bus->name, busname) == 0 &&
strcmp(dev_name(devlink->dev), devname) == 0) strcmp(dev_name(devlink->dev), devname) == 0)
return devlink; return devlink;
devl_unlock(devlink); devl_dev_unlock(devlink, dev_lock);
devlink_put(devlink); devlink_put(devlink);
} }
...@@ -93,11 +95,13 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs) ...@@ -93,11 +95,13 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs)
static int __devlink_nl_pre_doit(struct sk_buff *skb, struct genl_info *info, static int __devlink_nl_pre_doit(struct sk_buff *skb, struct genl_info *info,
u8 flags) u8 flags)
{ {
bool dev_lock = flags & DEVLINK_NL_FLAG_NEED_DEV_LOCK;
struct devlink_port *devlink_port; struct devlink_port *devlink_port;
struct devlink *devlink; struct devlink *devlink;
int err; int err;
devlink = devlink_get_from_attrs_lock(genl_info_net(info), info->attrs); devlink = devlink_get_from_attrs_lock(genl_info_net(info), info->attrs,
dev_lock);
if (IS_ERR(devlink)) if (IS_ERR(devlink))
return PTR_ERR(devlink); return PTR_ERR(devlink);
...@@ -117,7 +121,7 @@ static int __devlink_nl_pre_doit(struct sk_buff *skb, struct genl_info *info, ...@@ -117,7 +121,7 @@ static int __devlink_nl_pre_doit(struct sk_buff *skb, struct genl_info *info,
return 0; return 0;
unlock: unlock:
devl_unlock(devlink); devl_dev_unlock(devlink, dev_lock);
devlink_put(devlink); devlink_put(devlink);
return err; return err;
} }
...@@ -144,10 +148,11 @@ int devlink_nl_pre_doit_port_optional(const struct genl_split_ops *ops, ...@@ -144,10 +148,11 @@ int devlink_nl_pre_doit_port_optional(const struct genl_split_ops *ops,
static void __devlink_nl_post_doit(struct sk_buff *skb, struct genl_info *info, static void __devlink_nl_post_doit(struct sk_buff *skb, struct genl_info *info,
u8 flags) u8 flags)
{ {
bool dev_lock = flags & DEVLINK_NL_FLAG_NEED_DEV_LOCK;
struct devlink *devlink; struct devlink *devlink;
devlink = info->user_ptr[0]; devlink = info->user_ptr[0];
devl_unlock(devlink); devl_dev_unlock(devlink, dev_lock);
devlink_put(devlink); devlink_put(devlink);
} }
...@@ -165,7 +170,7 @@ static int devlink_nl_inst_single_dumpit(struct sk_buff *msg, ...@@ -165,7 +170,7 @@ static int devlink_nl_inst_single_dumpit(struct sk_buff *msg,
struct devlink *devlink; struct devlink *devlink;
int err; int err;
devlink = devlink_get_from_attrs_lock(sock_net(msg->sk), attrs); devlink = devlink_get_from_attrs_lock(sock_net(msg->sk), attrs, false);
if (IS_ERR(devlink)) if (IS_ERR(devlink))
return PTR_ERR(devlink); return PTR_ERR(devlink);
err = dump_one(msg, devlink, cb, flags | NLM_F_DUMP_FILTERED); err = dump_one(msg, devlink, cb, flags | NLM_F_DUMP_FILTERED);
......
...@@ -883,7 +883,8 @@ int devlink_nl_region_read_dumpit(struct sk_buff *skb, ...@@ -883,7 +883,8 @@ int devlink_nl_region_read_dumpit(struct sk_buff *skb,
start_offset = state->start_offset; start_offset = state->start_offset;
devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs); devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs,
false);
if (IS_ERR(devlink)) if (IS_ERR(devlink))
return PTR_ERR(devlink); return PTR_ERR(devlink);
......
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