[PATCH v2 1/6] sysfs: do not create empty directories if no attributes are present
When creating an attribute group, if it is named a subdirectory is created and the sysfs files are placed into that subdirectory. If no files are created, normally the directory would still be present, but it would be empty. Clean this up by removing the directory if no files were successfully created in the group at all.
Cc: Vinod Koul vkoul@kernel.org Cc: Bard Liao yung-chuan.liao@linux.intel.com Cc: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Cc: Sanyog Kale sanyog.r.kale@intel.com Cc: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- v2: new patch
Note, totally untested! The following soundwire patches will need this, if a soundwire developer could test this out, it would be most apreciated.
fs/sysfs/group.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index eeb0e3099421..9fe0b47db47f 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -31,12 +31,14 @@ static void remove_files(struct kernfs_node *parent, kernfs_remove_by_name(parent, (*bin_attr)->attr.name); }
+/* returns -ERROR if error, or >= 0 for number of files actually created */ static int create_files(struct kernfs_node *parent, struct kobject *kobj, kuid_t uid, kgid_t gid, const struct attribute_group *grp, int update) { struct attribute *const *attr; struct bin_attribute *const *bin_attr; + int files_created = 0; int error = 0, i;
if (grp->attrs) { @@ -65,6 +67,8 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj, gid, NULL); if (unlikely(error)) break; + + files_created++; } if (error) { remove_files(parent, grp); @@ -95,12 +99,15 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj, NULL); if (error) break; + files_created++; } if (error) remove_files(parent, grp); } exit: - return error; + if (error) + return error; + return files_created; }
@@ -146,10 +153,16 @@ static int internal_create_group(struct kobject *kobj, int update, kn = kobj->sd; kernfs_get(kn); error = create_files(kn, kobj, uid, gid, grp, update); - if (error) { + if (error <= 0) { + /* + * If an error happened _OR_ if no files were created in the + * attribute group, and we have a name for this group, delete + * the name so there's not an empty directory. + */ if (grp->name) kernfs_remove(kn); - } + } else + error = 0; kernfs_put(kn);
if (grp->name && update)
The sysfs logic already creates a list of groups for the device, so add the sdw_slave_dev_attr_group group to that list instead of having to do a two-step process of adding a group list and then an individual group.
This is a step on the way to moving all of the sysfs attribute handling into the default driver core attribute group logic so that the soundwire core does not have to do any of it manually.
Cc: Vinod Koul vkoul@kernel.org Cc: Bard Liao yung-chuan.liao@linux.intel.com Cc: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Cc: Sanyog Kale sanyog.r.kale@intel.com Cc: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- v2: rebased on 6.0-rc1
drivers/soundwire/sysfs_slave.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/soundwire/sysfs_slave.c b/drivers/soundwire/sysfs_slave.c index 3210359cd944..83e3f6cc3250 100644 --- a/drivers/soundwire/sysfs_slave.c +++ b/drivers/soundwire/sysfs_slave.c @@ -105,7 +105,10 @@ static struct attribute *slave_attrs[] = { &dev_attr_modalias.attr, NULL, }; -ATTRIBUTE_GROUPS(slave); + +static const struct attribute_group slave_attr_group = { + .attrs = slave_attrs, +};
static struct attribute *slave_dev_attrs[] = { &dev_attr_mipi_revision.attr, @@ -190,6 +193,12 @@ static const struct attribute_group dp0_group = { .name = "dp0", };
+static const struct attribute_group *slave_groups[] = { + &slave_attr_group, + &sdw_slave_dev_attr_group, + NULL, +}; + int sdw_slave_sysfs_init(struct sdw_slave *slave) { int ret; @@ -198,10 +207,6 @@ int sdw_slave_sysfs_init(struct sdw_slave *slave) if (ret < 0) return ret;
- ret = devm_device_add_group(&slave->dev, &sdw_slave_dev_attr_group); - if (ret < 0) - return ret; - if (slave->prop.dp0_prop) { ret = devm_device_add_group(&slave->dev, &dp0_group); if (ret < 0)
There's no need to special-case the dp0 sysfs attributes, the is_visible() callback in the attribute group can handle that for us, so add that and add it to the attribute group list making the logic simpler overall.
This is a step on the way to moving all of the sysfs attribute handling into the default driver core attribute group logic so that the soundwire core does not have to do any of it manually.
Cc: Vinod Koul vkoul@kernel.org Cc: Bard Liao yung-chuan.liao@linux.intel.com Cc: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Cc: Sanyog Kale sanyog.r.kale@intel.com Cc: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- v2: rebased on 6.0-rc1
drivers/soundwire/sysfs_slave.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/soundwire/sysfs_slave.c b/drivers/soundwire/sysfs_slave.c index 83e3f6cc3250..3723333a5c2b 100644 --- a/drivers/soundwire/sysfs_slave.c +++ b/drivers/soundwire/sysfs_slave.c @@ -174,6 +174,16 @@ static ssize_t words_show(struct device *dev, } static DEVICE_ATTR_RO(words);
+static umode_t dp0_is_visible(struct kobject *kobj, struct attribute *attr, + int n) +{ + struct sdw_slave *slave = dev_to_sdw_dev(kobj_to_dev(kobj)); + + if (slave->prop.dp0_prop) + return attr->mode; + return 0; +} + static struct attribute *dp0_attrs[] = { &dev_attr_max_word.attr, &dev_attr_min_word.attr, @@ -190,12 +200,14 @@ static struct attribute *dp0_attrs[] = { */ static const struct attribute_group dp0_group = { .attrs = dp0_attrs, + .is_visible = dp0_is_visible, .name = "dp0", };
static const struct attribute_group *slave_groups[] = { &slave_attr_group, &sdw_slave_dev_attr_group, + &dp0_group, NULL, };
@@ -207,12 +219,6 @@ int sdw_slave_sysfs_init(struct sdw_slave *slave) if (ret < 0) return ret;
- if (slave->prop.dp0_prop) { - ret = devm_device_add_group(&slave->dev, &dp0_group); - if (ret < 0) - return ret; - } - if (slave->prop.source_ports || slave->prop.sink_ports) { ret = sdw_slave_sysfs_dpn_init(slave); if (ret < 0)
The driver core supports the ability to handle the creation and removal of device-specific sysfs files in a race-free manner. Take advantage of that by converting this driver to use this by moving the sysfs attributes into a group and assigning the dev_groups pointer to it.
Cc: Vinod Koul vkoul@kernel.org Cc: Bard Liao yung-chuan.liao@linux.intel.com Cc: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Cc: Sanyog Kale sanyog.r.kale@intel.com Cc: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- v2: rebased on 6.0-rc1
drivers/soundwire/bus_type.c | 1 + drivers/soundwire/sysfs_local.h | 3 +++ drivers/soundwire/sysfs_slave.c | 6 +----- 3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/soundwire/bus_type.c b/drivers/soundwire/bus_type.c index 04b3529f8929..397fe9179369 100644 --- a/drivers/soundwire/bus_type.c +++ b/drivers/soundwire/bus_type.c @@ -215,6 +215,7 @@ int __sdw_register_driver(struct sdw_driver *drv, struct module *owner) drv->driver.probe = sdw_drv_probe; drv->driver.remove = sdw_drv_remove; drv->driver.shutdown = sdw_drv_shutdown; + drv->driver.dev_groups = sdw_attr_groups;
return driver_register(&drv->driver); } diff --git a/drivers/soundwire/sysfs_local.h b/drivers/soundwire/sysfs_local.h index 7268bc24c538..3ab8658a7782 100644 --- a/drivers/soundwire/sysfs_local.h +++ b/drivers/soundwire/sysfs_local.h @@ -11,6 +11,9 @@ /* basic attributes to report status of Slave (attachment, dev_num) */ extern const struct attribute_group *sdw_slave_status_attr_groups[];
+/* attributes for all soundwire devices */ +extern const struct attribute_group *sdw_attr_groups[]; + /* additional device-managed properties reported after driver probe */ int sdw_slave_sysfs_init(struct sdw_slave *slave); int sdw_slave_sysfs_dpn_init(struct sdw_slave *slave); diff --git a/drivers/soundwire/sysfs_slave.c b/drivers/soundwire/sysfs_slave.c index 3723333a5c2b..4c716c167493 100644 --- a/drivers/soundwire/sysfs_slave.c +++ b/drivers/soundwire/sysfs_slave.c @@ -204,7 +204,7 @@ static const struct attribute_group dp0_group = { .name = "dp0", };
-static const struct attribute_group *slave_groups[] = { +const struct attribute_group *sdw_attr_groups[] = { &slave_attr_group, &sdw_slave_dev_attr_group, &dp0_group, @@ -215,10 +215,6 @@ int sdw_slave_sysfs_init(struct sdw_slave *slave) { int ret;
- ret = devm_device_add_groups(&slave->dev, slave_groups); - if (ret < 0) - return ret; - if (slave->prop.source_ports || slave->prop.sink_ports) { ret = sdw_slave_sysfs_dpn_init(slave); if (ret < 0)
Now that sdw_slave_sysfs_init() only calls sdw_slave_sysfs_dpn_init(), just do that instead and remove sdw_slave_sysfs_init() to get it out of the way to save a bit of logic and code size.
Cc: Vinod Koul vkoul@kernel.org Cc: Bard Liao yung-chuan.liao@linux.intel.com Cc: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Cc: Sanyog Kale sanyog.r.kale@intel.com Cc: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- v2: rebased on 6.0-rc1
drivers/soundwire/bus_type.c | 4 ++-- drivers/soundwire/sysfs_local.h | 1 - drivers/soundwire/sysfs_slave.c | 13 ------------- drivers/soundwire/sysfs_slave_dpn.c | 3 +++ 4 files changed, 5 insertions(+), 16 deletions(-)
diff --git a/drivers/soundwire/bus_type.c b/drivers/soundwire/bus_type.c index 397fe9179369..5e488dd64724 100644 --- a/drivers/soundwire/bus_type.c +++ b/drivers/soundwire/bus_type.c @@ -123,8 +123,8 @@ static int sdw_drv_probe(struct device *dev) if (drv->ops && drv->ops->read_prop) drv->ops->read_prop(slave);
- /* init the sysfs as we have properties now */ - ret = sdw_slave_sysfs_init(slave); + /* init the dynamic sysfs attributes we need */ + ret = sdw_slave_sysfs_dpn_init(slave); if (ret < 0) dev_warn(dev, "Slave sysfs init failed:%d\n", ret);
diff --git a/drivers/soundwire/sysfs_local.h b/drivers/soundwire/sysfs_local.h index 3ab8658a7782..fa048e112629 100644 --- a/drivers/soundwire/sysfs_local.h +++ b/drivers/soundwire/sysfs_local.h @@ -15,7 +15,6 @@ extern const struct attribute_group *sdw_slave_status_attr_groups[]; extern const struct attribute_group *sdw_attr_groups[];
/* additional device-managed properties reported after driver probe */ -int sdw_slave_sysfs_init(struct sdw_slave *slave); int sdw_slave_sysfs_dpn_init(struct sdw_slave *slave);
#endif /* __SDW_SYSFS_LOCAL_H */ diff --git a/drivers/soundwire/sysfs_slave.c b/drivers/soundwire/sysfs_slave.c index 4c716c167493..070e0d84be94 100644 --- a/drivers/soundwire/sysfs_slave.c +++ b/drivers/soundwire/sysfs_slave.c @@ -211,19 +211,6 @@ const struct attribute_group *sdw_attr_groups[] = { NULL, };
-int sdw_slave_sysfs_init(struct sdw_slave *slave) -{ - int ret; - - if (slave->prop.source_ports || slave->prop.sink_ports) { - ret = sdw_slave_sysfs_dpn_init(slave); - if (ret < 0) - return ret; - } - - return 0; -} - /* * the status is shown in capital letters for UNATTACHED and RESERVED * on purpose, to highligh users to the fact that these status values diff --git a/drivers/soundwire/sysfs_slave_dpn.c b/drivers/soundwire/sysfs_slave_dpn.c index c4b6543c09fd..a3fb380ee519 100644 --- a/drivers/soundwire/sysfs_slave_dpn.c +++ b/drivers/soundwire/sysfs_slave_dpn.c @@ -283,6 +283,9 @@ int sdw_slave_sysfs_dpn_init(struct sdw_slave *slave) int ret; int i;
+ if (!slave->prop.source_ports && !slave->prop.sink_ports) + return 0; + mask = slave->prop.source_ports; for_each_set_bit(i, &mask, 32) { ret = add_all_attributes(&slave->dev, i, 1);
Now that we manually created our own attribute group list, the outdated ATTRIBUTE_GROUPS() comments can be removed as they are not needed at all.
Cc: Vinod Koul vkoul@kernel.org Cc: Bard Liao yung-chuan.liao@linux.intel.com Cc: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Cc: Sanyog Kale sanyog.r.kale@intel.com Cc: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- v2: rebased on 6.0-rc1
drivers/soundwire/sysfs_slave.c | 8 -------- 1 file changed, 8 deletions(-)
diff --git a/drivers/soundwire/sysfs_slave.c b/drivers/soundwire/sysfs_slave.c index 070e0d84be94..5b7666d27722 100644 --- a/drivers/soundwire/sysfs_slave.c +++ b/drivers/soundwire/sysfs_slave.c @@ -129,10 +129,6 @@ static struct attribute *slave_dev_attrs[] = { NULL, };
-/* - * we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory - * for device-level properties - */ static const struct attribute_group sdw_slave_dev_attr_group = { .attrs = slave_dev_attrs, .name = "dev-properties", @@ -194,10 +190,6 @@ static struct attribute *dp0_attrs[] = { NULL, };
-/* - * we don't use ATTRIBUTES_GROUP here since we want to add a subdirectory - * for dp0-level properties - */ static const struct attribute_group dp0_group = { .attrs = dp0_attrs, .is_visible = dp0_is_visible,
On 8/24/22 15:59, Greg Kroah-Hartman wrote:
When creating an attribute group, if it is named a subdirectory is created and the sysfs files are placed into that subdirectory. If no files are created, normally the directory would still be present, but it would be empty. Clean this up by removing the directory if no files were successfully created in the group at all.
Cc: Vinod Koul vkoul@kernel.org Cc: Bard Liao yung-chuan.liao@linux.intel.com Cc: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Cc: Sanyog Kale sanyog.r.kale@intel.com Cc: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
v2: new patch
Note, totally untested! The following soundwire patches will need this, if a soundwire developer could test this out, it would be most apreciated.
Not able to see the kernel boot with this first patch. The device is stuck with the cursor not even blinking. It seems our CI test devices are also stuck.
This is completely beyond my comfort zone but I can run more tests to root cause this.
fs/sysfs/group.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index eeb0e3099421..9fe0b47db47f 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -31,12 +31,14 @@ static void remove_files(struct kernfs_node *parent, kernfs_remove_by_name(parent, (*bin_attr)->attr.name); }
+/* returns -ERROR if error, or >= 0 for number of files actually created */ static int create_files(struct kernfs_node *parent, struct kobject *kobj, kuid_t uid, kgid_t gid, const struct attribute_group *grp, int update) { struct attribute *const *attr; struct bin_attribute *const *bin_attr;
int files_created = 0; int error = 0, i;
if (grp->attrs) {
@@ -65,6 +67,8 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj, gid, NULL); if (unlikely(error)) break;
} if (error) { remove_files(parent, grp);files_created++;
@@ -95,12 +99,15 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj, NULL); if (error) break;
} if (error) remove_files(parent, grp); }files_created++;
exit:
- return error;
- if (error)
return error;
- return files_created;
}
@@ -146,10 +153,16 @@ static int internal_create_group(struct kobject *kobj, int update, kn = kobj->sd; kernfs_get(kn); error = create_files(kn, kobj, uid, gid, grp, update);
- if (error) {
- if (error <= 0) {
/*
* If an error happened _OR_ if no files were created in the
* attribute group, and we have a name for this group, delete
* the name so there's not an empty directory.
if (grp->name) kernfs_remove(kn);*/
- }
} else
error = 0;
kernfs_put(kn);
if (grp->name && update)
On Wed, Aug 24, 2022 at 05:17:44PM +0200, Pierre-Louis Bossart wrote:
On 8/24/22 15:59, Greg Kroah-Hartman wrote:
When creating an attribute group, if it is named a subdirectory is created and the sysfs files are placed into that subdirectory. If no files are created, normally the directory would still be present, but it would be empty. Clean this up by removing the directory if no files were successfully created in the group at all.
Cc: Vinod Koul vkoul@kernel.org Cc: Bard Liao yung-chuan.liao@linux.intel.com Cc: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Cc: Sanyog Kale sanyog.r.kale@intel.com Cc: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
v2: new patch
Note, totally untested! The following soundwire patches will need this, if a soundwire developer could test this out, it would be most apreciated.
Not able to see the kernel boot with this first patch. The device is stuck with the cursor not even blinking. It seems our CI test devices are also stuck.
This is completely beyond my comfort zone but I can run more tests to root cause this.
Ick, ok, so much for sending out untested patches :(
I'll test and debug this tomorrow and resend a correct version, thanks for helping out here, sorry it didn't work.
greg k-h
On Wed, Aug 24, 2022 at 05:22:37PM +0200, Greg Kroah-Hartman wrote:
On Wed, Aug 24, 2022 at 05:17:44PM +0200, Pierre-Louis Bossart wrote:
On 8/24/22 15:59, Greg Kroah-Hartman wrote:
When creating an attribute group, if it is named a subdirectory is created and the sysfs files are placed into that subdirectory. If no files are created, normally the directory would still be present, but it would be empty. Clean this up by removing the directory if no files were successfully created in the group at all.
Cc: Vinod Koul vkoul@kernel.org Cc: Bard Liao yung-chuan.liao@linux.intel.com Cc: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Cc: Sanyog Kale sanyog.r.kale@intel.com Cc: alsa-devel@alsa-project.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
v2: new patch
Note, totally untested! The following soundwire patches will need this, if a soundwire developer could test this out, it would be most apreciated.
Not able to see the kernel boot with this first patch. The device is stuck with the cursor not even blinking. It seems our CI test devices are also stuck.
This is completely beyond my comfort zone but I can run more tests to root cause this.
Ick, ok, so much for sending out untested patches :(
I'll test and debug this tomorrow and resend a correct version, thanks for helping out here, sorry it didn't work.
I have run out of time to work on this for this week, I'll try to pick it up next week. Don't worry about the soundwire changes for now, I'll resend them when I get this all working properly.
thanks,
greg k-h
participants (2)
-
Greg Kroah-Hartman
-
Pierre-Louis Bossart