]> git.itanic.dy.fi Git - linux-stable/commitdiff
devlink: Allow taking device lock in pre_doit operations
authorIdo Schimmel <idosch@nvidia.com>
Wed, 15 Nov 2023 12:17:13 +0000 (13:17 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sat, 18 Nov 2023 17:38:50 +0000 (17:38 +0000)
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: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/devlink/devl_internal.h
net/devlink/health.c
net/devlink/netlink.c
net/devlink/region.c

index 178abaf74a10721435259693fd7b8cb71870043e..5ea2e2012e930695e7850e486588be18daf50b15 100644 (file)
@@ -152,7 +152,8 @@ typedef int devlink_nl_dump_one_func_t(struct sk_buff *msg,
                                       int flags);
 
 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,
                      devlink_nl_dump_one_func_t *dump_one);
index 695df61f8ac2a5de13f70d29c42c6d0a652c1b97..71ae121dc739dd878381a4b7a4035556aa4ff86a 100644 (file)
@@ -1151,7 +1151,8 @@ devlink_health_reporter_get_from_cb_lock(struct netlink_callback *cb)
        struct nlattr **attrs = info->attrs;
        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))
                return NULL;
 
index 5bb6624f3288e099fbc2df3fafd8d089e10b0c95..86f12531bf998bf8f1125bd26a3a168fee1c831a 100644 (file)
@@ -11,6 +11,7 @@
 
 #define DEVLINK_NL_FLAG_NEED_PORT              BIT(0)
 #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[] = {
        [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)
 }
 
 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;
        unsigned long index;
@@ -78,12 +80,12 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs)
        devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
 
        devlinks_xa_for_each_registered_get(net, index, devlink) {
-               devl_lock(devlink);
+               devl_dev_lock(devlink, dev_lock);
                if (devl_is_registered(devlink) &&
                    strcmp(devlink->dev->bus->name, busname) == 0 &&
                    strcmp(dev_name(devlink->dev), devname) == 0)
                        return devlink;
-               devl_unlock(devlink);
+               devl_dev_unlock(devlink, dev_lock);
                devlink_put(devlink);
        }
 
@@ -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,
                                 u8 flags)
 {
+       bool dev_lock = flags & DEVLINK_NL_FLAG_NEED_DEV_LOCK;
        struct devlink_port *devlink_port;
        struct devlink *devlink;
        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))
                return PTR_ERR(devlink);
 
@@ -117,7 +121,7 @@ static int __devlink_nl_pre_doit(struct sk_buff *skb, struct genl_info *info,
        return 0;
 
 unlock:
-       devl_unlock(devlink);
+       devl_dev_unlock(devlink, dev_lock);
        devlink_put(devlink);
        return err;
 }
@@ -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,
                                   u8 flags)
 {
+       bool dev_lock = flags & DEVLINK_NL_FLAG_NEED_DEV_LOCK;
        struct devlink *devlink;
 
        devlink = info->user_ptr[0];
-       devl_unlock(devlink);
+       devl_dev_unlock(devlink, dev_lock);
        devlink_put(devlink);
 }
 
@@ -165,7 +170,7 @@ static int devlink_nl_inst_single_dumpit(struct sk_buff *msg,
        struct devlink *devlink;
        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))
                return PTR_ERR(devlink);
        err = dump_one(msg, devlink, cb, flags | NLM_F_DUMP_FILTERED);
index 0aab7b82d67800bb2168c80147577a7f0c4260f2..e3bab458db940c2b3a2b3c568ee991ff138c9de0 100644 (file)
@@ -883,7 +883,8 @@ int devlink_nl_region_read_dumpit(struct sk_buff *skb,
 
        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))
                return PTR_ERR(devlink);