lkml.org 
[lkml]   [2021]   [Jan]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 143/199] driver core: Fix device link device name collision
    Date
    From: Saravana Kannan <saravanak@google.com>

    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: 287905e68dd2 ("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>

    ---
    Documentation/ABI/testing/sysfs-class-devlink | 4 +--
    Documentation/ABI/testing/sysfs-devices-consumer | 5 ++--
    Documentation/ABI/testing/sysfs-devices-supplier | 5 ++--
    drivers/base/core.c | 27 ++++++++++++-----------
    include/linux/device.h | 12 ++++++++++
    5 files changed, 35 insertions(+), 18 deletions(-)

    --- a/Documentation/ABI/testing/sysfs-class-devlink
    +++ b/Documentation/ABI/testing/sysfs-class-devlink
    @@ -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
    --- a/Documentation/ABI/testing/sysfs-devices-consumer
    +++ b/Documentation/ABI/testing/sysfs-devices-consumer
    @@ -4,5 +4,6 @@ Contact: Saravana Kannan <saravanak@goog
    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.
    --- a/Documentation/ABI/testing/sysfs-devices-supplier
    +++ b/Documentation/ABI/testing/sysfs-devices-supplier
    @@ -4,5 +4,6 @@ Contact: Saravana Kannan <saravanak@goog
    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.
    --- a/drivers/base/core.c
    +++ b/drivers/base/core.c
    @@ -363,7 +363,9 @@ static int devlink_add_symlinks(struct d
    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 d
    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 d
    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(stru
    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(stru
    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(stru

    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 stru
    * 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);

    --- a/include/linux/device.h
    +++ b/include/linux/device.h
    @@ -615,6 +615,18 @@ static inline const char *dev_name(const
    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

    \
     
     \ /
      Last update: 2021-01-26 10:56    [W:3.267 / U:0.612 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site