forked from luck/tmp_suning_uos_patched
driver core: Fix device link device name collision
commit e020ff611ba9be54e959e6b548038f8a020da1c9 upstream.
The device link device's name was of the form:
<supplier-dev-name>--<consumer-dev-name>
This can cause name collision as reported here [1] as device names are
not globally unique. Since device names have to be unique within the
bus/class, add the bus/class name as a prefix to the device names used to
construct the device link device name.
So the devuce link device's name will be of the form:
<supplier-bus-name>:<supplier-dev-name>--<consumer-bus-name>:<consumer-dev-name>
[1] - https://lore.kernel.org/lkml/20201229033440.32142-1-michael@walle.cc/
Fixes: 287905e68d
("driver core: Expose device link details in sysfs")
Cc: stable@vger.kernel.org
Reported-by: Michael Walle <michael@walle.cc>
Tested-by: Michael Walle <michael@walle.cc>
Signed-off-by: Saravana Kannan <saravanak@google.com>
Link: https://lore.kernel.org/r/20210110175408.1465657-1-saravanak@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
8cd3c48c1b
commit
b3bc56e3f5
|
@ -5,8 +5,8 @@ Description:
|
|||
Provide a place in sysfs for the device link objects in the
|
||||
kernel at any given time. The name of a device link directory,
|
||||
denoted as ... above, is of the form <supplier>--<consumer>
|
||||
where <supplier> is the supplier device name and <consumer> is
|
||||
the consumer device name.
|
||||
where <supplier> is the supplier bus:device name and <consumer>
|
||||
is the consumer bus:device name.
|
||||
|
||||
What: /sys/class/devlink/.../auto_remove_on
|
||||
Date: May 2020
|
||||
|
|
|
@ -4,5 +4,6 @@ Contact: Saravana Kannan <saravanak@google.com>
|
|||
Description:
|
||||
The /sys/devices/.../consumer:<consumer> are symlinks to device
|
||||
links where this device is the supplier. <consumer> denotes the
|
||||
name of the consumer in that device link. There can be zero or
|
||||
more of these symlinks for a given device.
|
||||
name of the consumer in that device link and is of the form
|
||||
bus:device name. There can be zero or more of these symlinks
|
||||
for a given device.
|
||||
|
|
|
@ -4,5 +4,6 @@ Contact: Saravana Kannan <saravanak@google.com>
|
|||
Description:
|
||||
The /sys/devices/.../supplier:<supplier> are symlinks to device
|
||||
links where this device is the consumer. <supplier> denotes the
|
||||
name of the supplier in that device link. There can be zero or
|
||||
more of these symlinks for a given device.
|
||||
name of the supplier in that device link and is of the form
|
||||
bus:device name. There can be zero or more of these symlinks
|
||||
for a given device.
|
||||
|
|
|
@ -363,7 +363,9 @@ static int devlink_add_symlinks(struct device *dev,
|
|||
struct device *con = link->consumer;
|
||||
char *buf;
|
||||
|
||||
len = max(strlen(dev_name(sup)), strlen(dev_name(con)));
|
||||
len = max(strlen(dev_bus_name(sup)) + strlen(dev_name(sup)),
|
||||
strlen(dev_bus_name(con)) + strlen(dev_name(con)));
|
||||
len += strlen(":");
|
||||
len += strlen("supplier:") + 1;
|
||||
buf = kzalloc(len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
|
@ -377,12 +379,12 @@ static int devlink_add_symlinks(struct device *dev,
|
|||
if (ret)
|
||||
goto err_con;
|
||||
|
||||
snprintf(buf, len, "consumer:%s", dev_name(con));
|
||||
snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
|
||||
ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf);
|
||||
if (ret)
|
||||
goto err_con_dev;
|
||||
|
||||
snprintf(buf, len, "supplier:%s", dev_name(sup));
|
||||
snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
|
||||
ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf);
|
||||
if (ret)
|
||||
goto err_sup_dev;
|
||||
|
@ -390,7 +392,7 @@ static int devlink_add_symlinks(struct device *dev,
|
|||
goto out;
|
||||
|
||||
err_sup_dev:
|
||||
snprintf(buf, len, "consumer:%s", dev_name(con));
|
||||
snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
|
||||
sysfs_remove_link(&sup->kobj, buf);
|
||||
err_con_dev:
|
||||
sysfs_remove_link(&link->link_dev.kobj, "consumer");
|
||||
|
@ -413,7 +415,9 @@ static void devlink_remove_symlinks(struct device *dev,
|
|||
sysfs_remove_link(&link->link_dev.kobj, "consumer");
|
||||
sysfs_remove_link(&link->link_dev.kobj, "supplier");
|
||||
|
||||
len = max(strlen(dev_name(sup)), strlen(dev_name(con)));
|
||||
len = max(strlen(dev_bus_name(sup)) + strlen(dev_name(sup)),
|
||||
strlen(dev_bus_name(con)) + strlen(dev_name(con)));
|
||||
len += strlen(":");
|
||||
len += strlen("supplier:") + 1;
|
||||
buf = kzalloc(len, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
|
@ -421,9 +425,9 @@ static void devlink_remove_symlinks(struct device *dev,
|
|||
return;
|
||||
}
|
||||
|
||||
snprintf(buf, len, "supplier:%s", dev_name(sup));
|
||||
snprintf(buf, len, "supplier:%s:%s", dev_bus_name(sup), dev_name(sup));
|
||||
sysfs_remove_link(&con->kobj, buf);
|
||||
snprintf(buf, len, "consumer:%s", dev_name(con));
|
||||
snprintf(buf, len, "consumer:%s:%s", dev_bus_name(con), dev_name(con));
|
||||
sysfs_remove_link(&sup->kobj, buf);
|
||||
kfree(buf);
|
||||
}
|
||||
|
@ -633,8 +637,9 @@ struct device_link *device_link_add(struct device *consumer,
|
|||
|
||||
link->link_dev.class = &devlink_class;
|
||||
device_set_pm_not_required(&link->link_dev);
|
||||
dev_set_name(&link->link_dev, "%s--%s",
|
||||
dev_name(supplier), dev_name(consumer));
|
||||
dev_set_name(&link->link_dev, "%s:%s--%s:%s",
|
||||
dev_bus_name(supplier), dev_name(supplier),
|
||||
dev_bus_name(consumer), dev_name(consumer));
|
||||
if (device_register(&link->link_dev)) {
|
||||
put_device(consumer);
|
||||
put_device(supplier);
|
||||
|
@ -1652,9 +1657,7 @@ const char *dev_driver_string(const struct device *dev)
|
|||
* never change once they are set, so they don't need special care.
|
||||
*/
|
||||
drv = READ_ONCE(dev->driver);
|
||||
return drv ? drv->name :
|
||||
(dev->bus ? dev->bus->name :
|
||||
(dev->class ? dev->class->name : ""));
|
||||
return drv ? drv->name : dev_bus_name(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(dev_driver_string);
|
||||
|
||||
|
|
|
@ -615,6 +615,18 @@ static inline const char *dev_name(const struct device *dev)
|
|||
return kobject_name(&dev->kobj);
|
||||
}
|
||||
|
||||
/**
|
||||
* dev_bus_name - Return a device's bus/class name, if at all possible
|
||||
* @dev: struct device to get the bus/class name of
|
||||
*
|
||||
* Will return the name of the bus/class the device is attached to. If it is
|
||||
* not attached to a bus/class, an empty string will be returned.
|
||||
*/
|
||||
static inline const char *dev_bus_name(const struct device *dev)
|
||||
{
|
||||
return dev->bus ? dev->bus->name : (dev->class ? dev->class->name : "");
|
||||
}
|
||||
|
||||
__printf(2, 3) int dev_set_name(struct device *dev, const char *name, ...);
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
|
|
Loading…
Reference in New Issue
Block a user