summaryrefslogtreecommitdiff
path: root/net/devlink/netlink.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2023-01-06 12:56:20 +0000
committerDavid S. Miller <davem@davemloft.net>2023-01-06 12:56:20 +0000
commit6bd4755c7c499dbcef46eaaeafa1a319da583b29 (patch)
tree4eb9d0f62f2fd24e44f7e5e83375d8d3c269cba1 /net/devlink/netlink.c
parent6b754d7bd007c5f68fbb2d9abd5c00d253b033d0 (diff)
parent82a3aef2e6af2fdd04d542c83b7a35990d94afc9 (diff)
Merge branch 'devlink-unregister'
Jakub Kicinski says: ==================== devlink: remove the wait-for-references on unregister Move the registration and unregistration of the devlink instances under their instance locks. Don't perform the netdev-style wait for all references when unregistering the instance. Instead the devlink instance refcount will only ensure that the memory of the instance is not freed. All places which acquire access to devlink instances via a reference must check that the instance is still registered under the instance lock. This fixes the problem of the netdev code accessing devlink instances before they are registered. RFC: https://lore.kernel.org/all/20221217011953.152487-1-kuba@kernel.org/ - rewrite the cover letter - rewrite the commit message for patch 1 - un-export and rename devl_is_alive - squash the netdevsim patches ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/devlink/netlink.c')
-rw-r--r--net/devlink/netlink.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c
index a552e723f4a6..b5b8ac6db2d1 100644
--- a/net/devlink/netlink.c
+++ b/net/devlink/netlink.c
@@ -82,7 +82,8 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
[DEVLINK_ATTR_REGION_DIRECT] = { .type = NLA_FLAG },
};
-struct devlink *devlink_get_from_attrs(struct net *net, struct nlattr **attrs)
+struct devlink *
+devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs)
{
struct devlink *devlink;
unsigned long index;
@@ -96,9 +97,12 @@ struct devlink *devlink_get_from_attrs(struct net *net, struct nlattr **attrs)
devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
devlinks_xa_for_each_registered_get(net, index, devlink) {
- if (strcmp(devlink->dev->bus->name, busname) == 0 &&
+ devl_lock(devlink);
+ if (devl_is_registered(devlink) &&
+ strcmp(devlink->dev->bus->name, busname) == 0 &&
strcmp(dev_name(devlink->dev), devname) == 0)
return devlink;
+ devl_unlock(devlink);
devlink_put(devlink);
}
@@ -113,10 +117,10 @@ static int devlink_nl_pre_doit(const struct genl_split_ops *ops,
struct devlink *devlink;
int err;
- devlink = devlink_get_from_attrs(genl_info_net(info), info->attrs);
+ devlink = devlink_get_from_attrs_lock(genl_info_net(info), info->attrs);
if (IS_ERR(devlink))
return PTR_ERR(devlink);
- devl_lock(devlink);
+
info->user_ptr[0] = devlink;
if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
devlink_port = devlink_port_get_from_info(devlink, info);
@@ -208,7 +212,12 @@ int devlink_nl_instance_iter_dump(struct sk_buff *msg,
devlink_dump_for_each_instance_get(msg, state, devlink) {
devl_lock(devlink);
- err = cmd->dump_one(msg, devlink, cb);
+
+ if (devl_is_registered(devlink))
+ err = cmd->dump_one(msg, devlink, cb);
+ else
+ err = 0;
+
devl_unlock(devlink);
devlink_put(devlink);