Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1259431 > unrolled thread
| Started by | Dmitry Torokhov <dmitry.torokhov@gmail.com> |
|---|---|
| First post | 2015-10-30 12:50 +0100 |
| Last post | 2015-10-30 16:20 +0100 |
| Articles | 3 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH] sysfs: add devm_sysfs_create_group() and friends Dmitry Torokhov <dmitry.torokhov@gmail.com> - 2015-10-30 12:50 +0100
Re: [PATCH] sysfs: add devm_sysfs_create_group() and friends Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2015-10-30 15:50 +0100
Re: [PATCH] sysfs: add devm_sysfs_create_group() and friends Dmitry Torokhov <dmitry.torokhov@gmail.com> - 2015-10-30 16:20 +0100
| From | Dmitry Torokhov <dmitry.torokhov@gmail.com> |
|---|---|
| Date | 2015-10-30 12:50 +0100 |
| Subject | [PATCH] sysfs: add devm_sysfs_create_group() and friends |
| Message-ID | <qpglX-5iu-7@gated-at.bofh.it> |
Many drivers create additional driver-specific device attributes when
binding to the device and providing managed version of sysfs_create_group()
will simplify unbinding and error handling in probe path for such drivers.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
fs/sysfs/group.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/sysfs.h | 10 ++++
2 files changed, 134 insertions(+)
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 39a0199..9511437 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -13,6 +13,7 @@
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/dcache.h>
+#include <linux/device.h>
#include <linux/namei.h>
#include <linux/err.h>
#include "sysfs.h"
@@ -352,3 +353,126 @@ void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
}
}
EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group);
+
+struct sysfs_group_devres {
+ const struct attribute_group *group;
+};
+
+static int devm_sysfs_group_match(struct device *dev, void *res, void *data)
+{
+ return ((struct sysfs_group_devres *)res)->group == data;
+}
+
+static void devm_sysfs_group_remove_group(struct device *dev, void *res)
+{
+ struct sysfs_group_devres *devres = res;
+ const struct attribute_group *group = devres->group;
+
+ dev_dbg(dev, "%s: removing group %p\n", __func__, group);
+ sysfs_remove_group(&dev->kobj, group);
+}
+
+/**
+ * devm_sysfs_create_group - given a device, create a managed attribute group
+ * @dev: The device to create the group for
+ * @grp: The attribute group to create
+ *
+ * This function creates a group for the first time. It will explicitly
+ * warn and error if any of the attribute files being created already exist.
+ *
+ * Returns 0 on success or error code on failure.
+ */
+int devm_sysfs_create_group(struct device *dev,
+ const struct attribute_group *grp)
+{
+ struct sysfs_group_devres *devres;
+ int error;
+
+ devres = devres_alloc(devm_sysfs_group_remove_group,
+ sizeof(*devres), GFP_KERNEL);
+ if (!devres)
+ return -ENOMEM;
+
+ error = sysfs_create_group(&dev->kobj, grp);
+ if (error) {
+ devres_free(devres);
+ return error;
+ }
+
+ devres_add(dev, devres);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(devm_sysfs_create_group);
+
+/**
+ * devm_sysfs_create_groups - create a bunch of managed attribute groups
+ * @dev: The device to create the group for
+ * @groups: The attribute groups to create, NULL terminated
+ *
+ * This function creates a bunch of managed attribute groups. If an error
+ * occurs when creating a group, all previously created groups will be
+ * removed, unwinding everything back to the original state when this
+ * function was called. It will explicitly warn and error if any of the
+ * attribute files being created already exist.
+ *
+ * Returns 0 on success or error code from sysfs_create_group on failure.
+ */
+int devm_sysfs_create_groups(struct device *dev,
+ const struct attribute_group **groups)
+{
+ int error;
+ int i;
+
+ if (!groups)
+ return 0;
+
+ for (i = 0; groups[i]; i++) {
+ error = devm_sysfs_create_group(dev, groups[i]);
+ if (error) {
+ while (--i >= 0)
+ devm_sysfs_remove_group(dev, groups[i]);
+ return error;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(devm_sysfs_create_groups);
+
+/**
+ * devm_sysfs_remove_group: remove a managed group from a device
+ * @dev: device to remove the group from
+ * @grp: group to remove
+ *
+ * This function removes a group of attributes from a device. The attributes
+ * previously have to have been created for this group, otherwise it will fail.
+ */
+void devm_sysfs_remove_group(struct device *dev,
+ const struct attribute_group *grp)
+{
+ WARN_ON(devres_release(dev, devm_sysfs_group_remove_group,
+ devm_sysfs_group_match,
+ /* cast away const */ (void *)grp));
+}
+EXPORT_SYMBOL_GPL(devm_sysfs_remove_group);
+
+/**
+ * devm_sysfs_remove_groups - remove a list of managed groups
+ *
+ * @dev: The device for the groups to be removed from
+ * @groups: NULL terminated list of groups to be removed
+ *
+ * If groups is not NULL, remove the specified groups from the device.
+ */
+void devm_sysfs_remove_groups(struct device *dev,
+ const struct attribute_group **groups)
+{
+ int i;
+
+ if (!groups)
+ return;
+
+ for (i = 0; groups[i]; i++)
+ devm_sysfs_remove_group(dev, groups[i]);
+}
+EXPORT_SYMBOL_GPL(devm_sysfs_remove_groups);
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 9f65758..b59a913 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -269,6 +269,16 @@ int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name,
void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
const char *link_name);
+struct device;
+int __must_check devm_sysfs_create_group(struct device *dev,
+ const struct attribute_group *grp);
+int __must_check devm_sysfs_create_groups(struct device *dev,
+ const struct attribute_group **groups);
+void devm_sysfs_remove_group(struct device *dev,
+ const struct attribute_group *grp);
+void devm_sysfs_remove_groups(struct device *dev,
+ const struct attribute_group **groups);
+
void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
int __must_check sysfs_init(void);
--
1.9.1
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
|---|---|
| Date | 2015-10-30 15:50 +0100 |
| Message-ID | <qpjaa-70R-11@gated-at.bofh.it> |
| In reply to | #1259431 |
On Fri, Oct 30, 2015 at 04:47:06AM -0700, Dmitry Torokhov wrote: > Many drivers create additional driver-specific device attributes when > binding to the device and providing managed version of sysfs_create_group() > will simplify unbinding and error handling in probe path for such drivers. But they really shouldn't, because if they do this, they have raced userspace and tools don't know that the files are present. I don't want to encourage drivers to do this at all, so I don't want to make it easier for them to do things incorrectly. Yes, I know that input does this for its devices, but I still think it is wrong and should be changed. Let's not let this problem spread to other subsystems please. thanks, greg k-h -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Dmitry Torokhov <dmitry.torokhov@gmail.com> |
|---|---|
| Date | 2015-10-30 16:20 +0100 |
| Message-ID | <qpjDc-7r6-27@gated-at.bofh.it> |
| In reply to | #1259558 |
On Fri, Oct 30, 2015 at 07:40:37AM -0700, Greg Kroah-Hartman wrote: > On Fri, Oct 30, 2015 at 04:47:06AM -0700, Dmitry Torokhov wrote: > > Many drivers create additional driver-specific device attributes when > > binding to the device and providing managed version of sysfs_create_group() > > will simplify unbinding and error handling in probe path for such drivers. > > But they really shouldn't, because if they do this, they have raced > userspace and tools don't know that the files are present. > > I don't want to encourage drivers to do this at all, so I don't want to > make it easier for them to do things incorrectly. The solution is not to forbid drivers from establishing attributes but rather notify userspace when device is fully bound to the driver. Then userspace that actually cares about these attributes will listen to proper events. We can either do KOBJ_BOUND/KOBJ_UNBOUND or reuse KOBJ_ONLINE/KOBJ_OFFLINE. I'd prefer the former (adding new events). > > Yes, I know that input does this for its devices, but I still think it > is wrong and should be changed. Let's not let this problem spread to > other subsystems please. Like HID, chargers, hwmon, wireless drivers, leds, backlights, platform drivers and so on? Where are platform devices supposed to create their attributes? There are more than 300 drivers that add new groups and 581 instance of device_create_file(). Let's be realistic here and see that additional attributes are not going anywhere and adding devm interface just helps getting error handling right. Thanks. -- Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web