devlink: Allow for devlink-rate nodes parent reassignment
authorMichal Wilczynski <michal.wilczynski@intel.com>
Tue, 15 Nov 2022 10:48:18 +0000 (11:48 +0100)
committerJakub Kicinski <kuba@kernel.org>
Fri, 18 Nov 2022 05:41:26 +0000 (21:41 -0800)
Currently it's not possible to reassign the parent of the node using one
command. As the previous commit introduced a way to export entire
hierarchy from the driver, being able to modify and reassign parents
become important. This way user might easily change QoS settings without
interrupting traffic.

Example command:
devlink port function rate set pci/0000:4b:00.0/1 parent node_custom_1

This reassigns leaf node parent to node_custom_1.

Signed-off-by: Michal Wilczynski <michal.wilczynski@intel.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/core/devlink.c

index 3dfee7c..61d4315 100644 (file)
@@ -1887,10 +1887,8 @@ devlink_nl_rate_parent_node_set(struct devlink_rate *devlink_rate,
        int err = -EOPNOTSUPP;
 
        parent = devlink_rate->parent;
-       if (parent && len) {
-               NL_SET_ERR_MSG_MOD(info->extack, "Rate object already has parent.");
-               return -EBUSY;
-       } else if (parent && !len) {
+
+       if (parent && !len) {
                if (devlink_rate_is_leaf(devlink_rate))
                        err = ops->rate_leaf_parent_set(devlink_rate, NULL,
                                                        devlink_rate->priv, NULL,
@@ -1904,7 +1902,7 @@ devlink_nl_rate_parent_node_set(struct devlink_rate *devlink_rate,
 
                refcount_dec(&parent->refcnt);
                devlink_rate->parent = NULL;
-       } else if (!parent && len) {
+       } else if (len) {
                parent = devlink_rate_node_get_by_name(devlink, parent_name);
                if (IS_ERR(parent))
                        return -ENODEV;
@@ -1931,6 +1929,10 @@ devlink_nl_rate_parent_node_set(struct devlink_rate *devlink_rate,
                if (err)
                        return err;
 
+               if (devlink_rate->parent)
+                       /* we're reassigning to other parent in this case */
+                       refcount_dec(&devlink_rate->parent->refcnt);
+
                refcount_inc(&parent->refcnt);
                devlink_rate->parent = parent;
        }