提交 e020ff61 编写于 作者: S Saravana Kannan 提交者: Greg Kroah-Hartman

driver core: Fix device link device name collision

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: 287905e6 ("driver core: Expose device link details in sysfs")
Cc: stable@vger.kernel.org
Reported-by: NMichael Walle <michael@walle.cc>
Tested-by: NMichael Walle <michael@walle.cc>
Signed-off-by: NSaravana Kannan <saravanak@google.com>
Link: https://lore.kernel.org/r/20210110175408.1465657-1-saravanak@google.comSigned-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 3d1cf435
...@@ -5,8 +5,8 @@ Description: ...@@ -5,8 +5,8 @@ Description:
Provide a place in sysfs for the device link objects in the Provide a place in sysfs for the device link objects in the
kernel at any given time. The name of a device link directory, kernel at any given time. The name of a device link directory,
denoted as ... above, is of the form <supplier>--<consumer> denoted as ... above, is of the form <supplier>--<consumer>
where <supplier> is the supplier device name and <consumer> is where <supplier> is the supplier bus:device name and <consumer>
the consumer device name. is the consumer bus:device name.
What: /sys/class/devlink/.../auto_remove_on What: /sys/class/devlink/.../auto_remove_on
Date: May 2020 Date: May 2020
......
...@@ -4,5 +4,6 @@ Contact: Saravana Kannan <saravanak@google.com> ...@@ -4,5 +4,6 @@ Contact: Saravana Kannan <saravanak@google.com>
Description: Description:
The /sys/devices/.../consumer:<consumer> are symlinks to device The /sys/devices/.../consumer:<consumer> are symlinks to device
links where this device is the supplier. <consumer> denotes the links where this device is the supplier. <consumer> denotes the
name of the consumer in that device link. There can be zero or name of the consumer in that device link and is of the form
more of these symlinks for a given device. 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> ...@@ -4,5 +4,6 @@ Contact: Saravana Kannan <saravanak@google.com>
Description: Description:
The /sys/devices/.../supplier:<supplier> are symlinks to device The /sys/devices/.../supplier:<supplier> are symlinks to device
links where this device is the consumer. <supplier> denotes the links where this device is the consumer. <supplier> denotes the
name of the supplier in that device link. There can be zero or name of the supplier in that device link and is of the form
more of these symlinks for a given device. bus:device name. There can be zero or more of these symlinks
for a given device.
...@@ -471,7 +471,9 @@ static int devlink_add_symlinks(struct device *dev, ...@@ -471,7 +471,9 @@ static int devlink_add_symlinks(struct device *dev,
struct device *con = link->consumer; struct device *con = link->consumer;
char *buf; 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; len += strlen("supplier:") + 1;
buf = kzalloc(len, GFP_KERNEL); buf = kzalloc(len, GFP_KERNEL);
if (!buf) if (!buf)
...@@ -485,12 +487,12 @@ static int devlink_add_symlinks(struct device *dev, ...@@ -485,12 +487,12 @@ static int devlink_add_symlinks(struct device *dev,
if (ret) if (ret)
goto err_con; 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); ret = sysfs_create_link(&sup->kobj, &link->link_dev.kobj, buf);
if (ret) if (ret)
goto err_con_dev; 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); ret = sysfs_create_link(&con->kobj, &link->link_dev.kobj, buf);
if (ret) if (ret)
goto err_sup_dev; goto err_sup_dev;
...@@ -498,7 +500,7 @@ static int devlink_add_symlinks(struct device *dev, ...@@ -498,7 +500,7 @@ static int devlink_add_symlinks(struct device *dev,
goto out; goto out;
err_sup_dev: 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); sysfs_remove_link(&sup->kobj, buf);
err_con_dev: err_con_dev:
sysfs_remove_link(&link->link_dev.kobj, "consumer"); sysfs_remove_link(&link->link_dev.kobj, "consumer");
...@@ -521,7 +523,9 @@ static void devlink_remove_symlinks(struct device *dev, ...@@ -521,7 +523,9 @@ static void devlink_remove_symlinks(struct device *dev,
sysfs_remove_link(&link->link_dev.kobj, "consumer"); sysfs_remove_link(&link->link_dev.kobj, "consumer");
sysfs_remove_link(&link->link_dev.kobj, "supplier"); 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; len += strlen("supplier:") + 1;
buf = kzalloc(len, GFP_KERNEL); buf = kzalloc(len, GFP_KERNEL);
if (!buf) { if (!buf) {
...@@ -529,9 +533,9 @@ static void devlink_remove_symlinks(struct device *dev, ...@@ -529,9 +533,9 @@ static void devlink_remove_symlinks(struct device *dev,
return; 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); 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); sysfs_remove_link(&sup->kobj, buf);
kfree(buf); kfree(buf);
} }
...@@ -752,8 +756,9 @@ struct device_link *device_link_add(struct device *consumer, ...@@ -752,8 +756,9 @@ struct device_link *device_link_add(struct device *consumer,
link->link_dev.class = &devlink_class; link->link_dev.class = &devlink_class;
device_set_pm_not_required(&link->link_dev); device_set_pm_not_required(&link->link_dev);
dev_set_name(&link->link_dev, "%s--%s", dev_set_name(&link->link_dev, "%s:%s--%s:%s",
dev_name(supplier), dev_name(consumer)); dev_bus_name(supplier), dev_name(supplier),
dev_bus_name(consumer), dev_name(consumer));
if (device_register(&link->link_dev)) { if (device_register(&link->link_dev)) {
put_device(consumer); put_device(consumer);
put_device(supplier); put_device(supplier);
...@@ -1823,9 +1828,7 @@ const char *dev_driver_string(const struct device *dev) ...@@ -1823,9 +1828,7 @@ const char *dev_driver_string(const struct device *dev)
* never change once they are set, so they don't need special care. * never change once they are set, so they don't need special care.
*/ */
drv = READ_ONCE(dev->driver); drv = READ_ONCE(dev->driver);
return drv ? drv->name : return drv ? drv->name : dev_bus_name(dev);
(dev->bus ? dev->bus->name :
(dev->class ? dev->class->name : ""));
} }
EXPORT_SYMBOL(dev_driver_string); EXPORT_SYMBOL(dev_driver_string);
......
...@@ -609,6 +609,18 @@ static inline const char *dev_name(const struct device *dev) ...@@ -609,6 +609,18 @@ static inline const char *dev_name(const struct device *dev)
return kobject_name(&dev->kobj); 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, ...); __printf(2, 3) int dev_set_name(struct device *dev, const char *name, ...);
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册