Skip to contentSkip to conversation

Driver core and sysfs changes for attribute groups

PATCH Superseded Greg Kroah-Hartman 3 participants 40 messages Jul 10, 2013 – Jul 14, 2013

Subsystems (4)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

Hi all,

Guenter and Oliver have been pointing out a few limitations of the driver core's ability to create files properly (i.e. in a way that doesn't race with userspace.) The driver core allows this, but it doesn't export that ability to drivers very easily, and for binary files, not at all.

So here's a set of 6 patches that I'll be queueing up to go to Linus in time for 3.11 so that people can start using them in their driver subsystems. It adds some new macros to make using attributes and attribute groups easier, adds binary file capabilities to attribute groups, and finally, lets subsystems (like platform drivers) set a attribute group for when their device is created.

If anyone has any problems with these patches, please let me know.

Guenter, I've tweaked your original patch a bit, changing the name of the function and putting the kernel doc comments in the correct place so the build doesn't complain about it.

I also have a set of follow-on patches, about 50+ big so far, that goes through the kernel and converts different drivers and subsystems to properly use attribute groups, instead of open-coding binary files and attributes. Those patches will be sent out later, and will be for 3.12 as they aren't needed at the moment, this infrastructure changes are needed first.

thanks,

greg k-h

author maintainer
#1 lore raw

PATCH 1/6 sysfs.h: add __ATTR_RW() macro

A number of parts of the kernel created their own version of this, might as well have the sysfs core provide it instead.

---
 include/linux/sysfs.h | 2 ++
 kernel/events/core.c  | 2 --
 mm/backing-dev.c      | 2 --
 3 files changed, 2 insertions(+), 4 deletions(-)
include/linux/sysfs.h +2 -0
index e2cee22..9cd20c8 100644
@@ -79,6 +79,8 @@ struct attribute_group {
 	.show	= _name##_show,					\
 }
 
+#define __ATTR_RW(_name) __ATTR(_name, 0644, _name##_show, _name##_store)
+
 #define __ATTR_NULL { .attr = { .name = NULL } }
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
kernel/events/core.c +0 -2
index 1db3af9..45a21ae 100644
@@ -6212,8 +6212,6 @@ perf_event_mux_interval_ms_store(struct device *dev,
 	return count;
 }
 
-#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
-
 static struct device_attribute pmu_dev_attrs[] = {
 	__ATTR_RO(type),
 	__ATTR_RW(perf_event_mux_interval_ms),
mm/backing-dev.c +0 -2
index d014ee5..e04454c 100644
@@ -232,8 +232,6 @@ static ssize_t stable_pages_required_show(struct device *dev,
 			bdi_cap_stable_pages_required(bdi) ? 1 : 0);
 }
 
-#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
-
 static struct device_attribute bdi_dev_attrs[] = {
 	__ATTR_RW(read_ahead_kb),
 	__ATTR_RW(min_ratio),
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
author maintainer
#2 lore raw

PATCH 2/6 sysfs.h: add ATTRIBUTE_GROUPS() macro

In reply to Greg Kroah-Hartman

To make it easier for driver subsystems to work with attribute groups, create the ATTRIBUTE_GROUPS macro to remove some of the repetitive typing for the most common use for attribute groups.

---
 include/linux/sysfs.h | 9 +++++++++
 1 file changed, 9 insertions(+)
include/linux/sysfs.h +9 -0
index 9cd20c8..f62ff01 100644
@@ -94,6 +94,15 @@ struct attribute_group {
 #define __ATTR_IGNORE_LOCKDEP	__ATTR
 #endif
 
+#define ATTRIBUTE_GROUPS(name)					\
+static const struct attribute_group name##_group = {		\
+	.attrs = name##_attrs,					\
+};								\
+static const struct attribute_group *name##_groups[] = {	\
+	&name##_group,						\
+	NULL,							\
+}
+
 #define attr_name(_attr) (_attr).attr.name
 
 struct file;
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
author maintainer
#3 lore raw

PATCH 3/6 sysfs.h: add BIN_ATTR macro

In reply to Greg Kroah-Hartman

This makes it easier to create static binary attributes, which is needed in a number of drivers, instead of "open coding" them.

---
 include/linux/sysfs.h | 9 +++++++++
 1 file changed, 9 insertions(+)
include/linux/sysfs.h +9 -0
index f62ff01..d50a96b 100644
@@ -132,6 +132,15 @@ struct bin_attribute {
  */
 #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
 
+/* macro to create static binary attributes easier */
+#define BIN_ATTR(_name, _mode, _read, _write, _size)		\
+struct bin_attribute bin_attr_##_name = {			\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.read	= _read,					\
+	.write	= _write,					\
+	.size	= _size,					\
+}
+
 struct sysfs_ops {
 	ssize_t	(*show)(struct kobject *, struct attribute *,char *);
 	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
author maintainer
#4 lore raw

PATCH 4/6 driver core: add DEVICE_ATTR_RW and DEVICE_ATTR_RO macros

In reply to Greg Kroah-Hartman

Make it easier to create attributes without having to always audit the mode settings.

---
 include/linux/device.h | 4 ++++
 1 file changed, 4 insertions(+)
include/linux/device.h +4 -0
index bcf8c0d..1d546a0 100644
@@ -512,6 +512,10 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
 
 #define DEVICE_ATTR(_name, _mode, _show, _store) \
 	struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
+#define DEVICE_ATTR_RW(_name) \
+	struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
+#define DEVICE_ATTR_RO(_name) \
+	struct device_attribute dev_attr_##_name = __ATTR_RO(_name)
 #define DEVICE_ULONG_ATTR(_name, _mode, _var) \
 	struct dev_ext_attribute dev_attr_##_name = \
 		{ __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
author maintainer
#5 lore raw

PATCH 5/6 sysfs: add support for binary attributes in groups

In reply to Greg Kroah-Hartman

groups should be able to support binary attributes, just like it supports "normal" attributes. This lets us only handle one type of structure, groups, throughout the driver core and subsystems, making binary attributes a "full fledged" part of the driver model, and not something just "tacked on".

---
 fs/sysfs/group.c      | 18 ++++++++++++++++--
 include/linux/sysfs.h |  4 ++--
 2 files changed, 18 insertions(+), 4 deletions(-)
fs/sysfs/group.c +16 -2
index aec3d5c..d8d8a8f 100644
@@ -20,16 +20,19 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
 			 const struct attribute_group *grp)
 {
 	struct attribute *const* attr;
-	int i;
+	struct bin_attribute *const* bin_attr;
 
-	for (i = 0, attr = grp->attrs; *attr; i++, attr++)
+	for (attr = grp->attrs; *attr; attr++)
 		sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
+	for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
+		sysfs_remove_bin_file(kobj, *bin_attr);
 }
 
 static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
 			const struct attribute_group *grp, int update)
 {
 	struct attribute *const* attr;
+	struct bin_attribute *const* bin_attr;
 	int error = 0, i;
 
 	for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
@@ -52,6 +55,17 @@ static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
 	}
 	if (error)
 		remove_files(dir_sd, kobj, grp);
+
+	for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
+		if (update)
+			sysfs_remove_bin_file(kobj, *bin_attr);
+		error = sysfs_create_bin_file(kobj, *bin_attr);
+		if (error)
+			break;
+	}
+	if (error)
+		remove_files(dir_sd, kobj, grp);
+
 	return error;
 }
 
include/linux/sysfs.h +2 -2
index d50a96b..2c3b6a3 100644
@@ -21,6 +21,7 @@
 
 struct kobject;
 struct module;
+struct bin_attribute;
 enum kobj_ns_type;
 
 struct attribute {
@@ -59,10 +60,9 @@ struct attribute_group {
 	umode_t			(*is_visible)(struct kobject *,
 					      struct attribute *, int);
 	struct attribute	**attrs;
+	struct bin_attribute	**bin_attrs;
 };
 
-
-
 /**
  * Use these macros to make defining attributes easier. See include/linux/device.h
  * for examples..
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
author maintainer
#6 lore raw

PATCH 6/6 driver core: Introduce device_create_groups

In reply to Greg Kroah-Hartman

From: Guenter Roeck <[email protected]>

From: Guenter Roeck <[email protected]>

device_create_groups lets callers create devices as well as associated sysfs attributes with a single call. This avoids race conditions seen if sysfs attributes on new devices are created later.

[fixed up comment block placement and add checks for printk buffer formats - gregkh]

---
 drivers/base/core.c    | 111 ++++++++++++++++++++++++++++++++++++-------------
 include/linux/device.h |   5 +++
 2 files changed, 88 insertions(+), 28 deletions(-)
drivers/base/core.c +83 -28
index dc3ea23..a8aae18 100644
@@ -1667,34 +1667,11 @@ static void device_create_release(struct device *dev)
 	kfree(dev);
 }
 
-/**
- * device_create_vargs - creates a device and registers it with sysfs
- * @class: pointer to the struct class that this device should be registered to
- * @parent: pointer to the parent struct device of this new device, if any
- * @devt: the dev_t for the char device to be added
- * @drvdata: the data to be added to the device for callbacks
- * @fmt: string for the device's name
- * @args: va_list for the device's name
- *
- * This function can be used by char device classes.  A struct device
- * will be created in sysfs, registered to the specified class.
- *
- * A "dev" file will be created, showing the dev_t for the device, if
- * the dev_t is not 0,0.
- * If a pointer to a parent struct device is passed in, the newly created
- * struct device will be a child of that device in sysfs.
- * The pointer to the struct device will be returned from the call.
- * Any further sysfs files that might be required can be created using this
- * pointer.
- *
- * Returns &struct device pointer on success, or ERR_PTR() on error.
- *
- * Note: the struct class passed to this function must have previously
- * been created with a call to class_create().
- */
-struct device *device_create_vargs(struct class *class, struct device *parent,
-				   dev_t devt, void *drvdata, const char *fmt,
-				   va_list args)
+static struct device *
+device_create_groups_vargs(struct class *class, struct device *parent,
+			   dev_t devt, void *drvdata,
+			   const struct attribute_group **groups,
+			   const char *fmt, va_list args)
 {
 	struct device *dev = NULL;
 	int retval = -ENODEV;
@@ -1711,6 +1688,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
 	dev->devt = devt;
 	dev->class = class;
 	dev->parent = parent;
+	dev->groups = groups;
 	dev->release = device_create_release;
 	dev_set_drvdata(dev, drvdata);
 
@@ -1728,6 +1706,39 @@ error:
 	put_device(dev);
 	return ERR_PTR(retval);
 }
+
+/**
+ * device_create_vargs - creates a device and registers it with sysfs
+ * @class: pointer to the struct class that this device should be registered to
+ * @parent: pointer to the parent struct device of this new device, if any
+ * @devt: the dev_t for the char device to be added
+ * @drvdata: the data to be added to the device for callbacks
+ * @fmt: string for the device's name
+ * @args: va_list for the device's name
+ *
+ * This function can be used by char device classes.  A struct device
+ * will be created in sysfs, registered to the specified class.
+ *
+ * A "dev" file will be created, showing the dev_t for the device, if
+ * the dev_t is not 0,0.
+ * If a pointer to a parent struct device is passed in, the newly created
+ * struct device will be a child of that device in sysfs.
+ * The pointer to the struct device will be returned from the call.
+ * Any further sysfs files that might be required can be created using this
+ * pointer.
+ *
+ * Returns &struct device pointer on success, or ERR_PTR() on error.
+ *
+ * Note: the struct class passed to this function must have previously
+ * been created with a call to class_create().
+ */
+struct device *device_create_vargs(struct class *class, struct device *parent,
+				   dev_t devt, void *drvdata, const char *fmt,
+				   va_list args)
+{
+	return device_create_groups_vargs(class, parent, devt, drvdata, NULL,
+					  fmt, args);
+}
 EXPORT_SYMBOL_GPL(device_create_vargs);
 
 /**
@@ -1767,6 +1778,50 @@ struct device *device_create(struct class *class, struct device *parent,
 }
 EXPORT_SYMBOL_GPL(device_create);
 
+/**
+ * device_create_with_groups - creates a device and registers it with sysfs
+ * @class: pointer to the struct class that this device should be registered to
+ * @parent: pointer to the parent struct device of this new device, if any
+ * @devt: the dev_t for the char device to be added
+ * @drvdata: the data to be added to the device for callbacks
+ * @groups: NULL-terminated list of attribute groups to be created
+ * @fmt: string for the device's name
+ *
+ * This function can be used by char device classes.  A struct device
+ * will be created in sysfs, registered to the specified class.
+ * Additional attributes specified in the groups parameter will also
+ * be created automatically.
+ *
+ * A "dev" file will be created, showing the dev_t for the device, if
+ * the dev_t is not 0,0.
+ * If a pointer to a parent struct device is passed in, the newly created
+ * struct device will be a child of that device in sysfs.
+ * The pointer to the struct device will be returned from the call.
+ * Any further sysfs files that might be required can be created using this
+ * pointer.
+ *
+ * Returns &struct device pointer on success, or ERR_PTR() on error.
+ *
+ * Note: the struct class passed to this function must have previously
+ * been created with a call to class_create().
+ */
+struct device *device_create_with_groups(struct class *class,
+					 struct device *parent, dev_t devt,
+					 void *drvdata,
+					 const struct attribute_group **groups,
+					 const char *fmt, ...)
+{
+	va_list vargs;
+	struct device *dev;
+
+	va_start(vargs, fmt);
+	dev = device_create_groups_vargs(class, parent, devt, drvdata, groups,
+					 fmt, vargs);
+	va_end(vargs);
+	return dev;
+}
+EXPORT_SYMBOL_GPL(device_create_with_groups);
+
 static int __match_devt(struct device *dev, const void *data)
 {
 	const dev_t *devt = data;
include/linux/device.h +5 -0
index 1d546a0..dce20e4 100644
@@ -928,6 +928,11 @@ extern __printf(5, 6)
 struct device *device_create(struct class *cls, struct device *parent,
 			     dev_t devt, void *drvdata,
 			     const char *fmt, ...);
+extern __printf(6, 7)
+struct device *device_create_with_groups(struct class *cls,
+			     struct device *parent, dev_t devt, void *drvdata,
+			     const struct attribute_group **groups,
+			     const char *fmt, ...);
 extern void device_destroy(struct class *cls, dev_t devt);
 
 /*
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
#7 lore raw
In reply to Greg Kroah-Hartman
Quoted 1 line · Greg Kroah-Hartman

Hi all,

Hey Greg,

Quoted 6 lines

Guenter and Oliver have been pointing out a few limitations of the driver core's ability to create files properly (i.e. in a way that doesn't race with userspace.) The driver core allows this, but it doesn't export that ability to drivers very easily, and for binary files, not at all.

Exactly, even the patch you supplied didn't help, as it created the binary attributes for devices, not device_drivers or platform_drivers.

Quoted 7 lines

So here's a set of 6 patches that I'll be queueing up to go to Linus in time for 3.11 so that people can start using them in their driver subsystems. It adds some new macros to make using attributes and attribute groups easier, adds binary file capabilities to attribute groups, and finally, lets subsystems (like platform drivers) set a attribute group for when their device is created.

Oh, that does some like iceing on the cake.

Quoted 3 lines

If anyone has any problems with these patches, please let me know.

I will try this patch set immediately and report back.

Quoted 4 lines

Guenter, I've tweaked your original patch a bit, changing the name of the function and putting the kernel doc comments in the correct place so the build doesn't complain about it.

Quoted 8 lines

I also have a set of follow-on patches, about 50+ big so far, that goes through the kernel and converts different drivers and subsystems to properly use attribute groups, instead of open-coding binary files and attributes. Those patches will be sent out later, and will be for 3.12 as they aren't needed at the moment, this infrastructure changes are needed first.

thanks,

Thank you Greg, this is far more robust that what I cooked up (adding bin_attrs to struct device_driver. I was just going to send it to the list as well when I saw this message :)

Quoted 3 lines

greg k-h

Oliver

#8 lore raw
In reply to Greg Kroah-Hartman
Quoted 15 lines · Greg Kroah-Hartman

Hi all,

Guenter and Oliver have been pointing out a few limitations of the driver core's ability to create files properly (i.e. in a way that doesn't race with userspace.) The driver core allows this, but it doesn't export that ability to drivers very easily, and for binary files, not at all.

So here's a set of 6 patches that I'll be queueing up to go to Linus in time for 3.11 so that people can start using them in their driver subsystems. It adds some new macros to make using attributes and attribute groups easier, adds binary file capabilities to attribute groups, and finally, lets subsystems (like platform drivers) set a attribute group for when their device is created.

Quoted 6 lines

If anyone has any problems with these patches, please let me know.

Guenter, I've tweaked your original patch a bit, changing the name of the function and putting the kernel doc comments in the correct place so the build doesn't complain about it.

I like it - thanks a lot for picking that up. I think there are several drivers who could and should use the new API call (gpio, infiniband/umad, c2port, ptp, scsi/osst, android/timed_output, asus_oled are some examples).

For hwmon, I ended up having to handle device creation internally after all. Reason is that I also had to set device->type to a new hwmon device type. That in turn was necessary to be able to support the hwmon 'name' attribute properly (it has to be optional, meaning I could not use class->dev_attrs but had to use device_type->groups instead). I hope I can send out a revised series of patches soon .. only I'll leave for pto next week and I am bugged down with other work right now, so it may have to wait until after I return.

Wonder if it would make sense to support a core driver API call for that purpose as well - ie one that not only has the additional groups argument, but one that (also ?) accepts a pointer to the the device type. I didn't spend any time tracking down potential users, though, so I may be off track here.

Quoted 7 lines

I also have a set of follow-on patches, about 50+ big so far, that goes through the kernel and converts different drivers and subsystems to properly use attribute groups, instead of open-coding binary files and attributes. Those patches will be sent out later, and will be for 3.12 as they aren't needed at the moment, this infrastructure changes are needed first.

Wow ... you really got into cleanup mode!

Thanks,
Guenter

author maintainer
#9 lore raw
Quoted 18 lines · Guenter Roeck
Quoted 17 lines · Greg Kroah-Hartman

Hi all,

Guenter and Oliver have been pointing out a few limitations of the driver core's ability to create files properly (i.e. in a way that doesn't race with userspace.) The driver core allows this, but it doesn't export that ability to drivers very easily, and for binary files, not at all.

So here's a set of 6 patches that I'll be queueing up to go to Linus in time for 3.11 so that people can start using them in their driver subsystems. It adds some new macros to make using attributes and attribute groups easier, adds binary file capabilities to attribute groups, and finally, lets subsystems (like platform drivers) set a attribute group for when their device is created.

If anyone has any problems with these patches, please let me know.

Quoted 7 lines
Quoted 4 lines

Guenter, I've tweaked your original patch a bit, changing the name of the function and putting the kernel doc comments in the correct place so the build doesn't complain about it.

I like it - thanks a lot for picking that up. I think there are several drivers who could and should use the new API call (gpio, infiniband/umad, c2port, ptp, scsi/osst, android/timed_output, asus_oled are some examples).

Yes, I'll be sweeping the tree for the next few released doing all of this. The amount of sysfs "cruft" that has accumulated in the past few years since I last looked is crazy...

Quoted 8 lines

For hwmon, I ended up having to handle device creation internally after all. Reason is that I also had to set device->type to a new hwmon device type. That in turn was necessary to be able to support the hwmon 'name' attribute properly (it has to be optional, meaning I could not use class->dev_attrs but had to use device_type->groups instead). I hope I can send out a revised series of patches soon .. only I'll leave for pto next week and I am bugged down with other work right now, so it may have to wait until after I return.

Quoted 4 lines

Wonder if it would make sense to support a core driver API call for that purpose as well - ie one that not only has the additional groups argument, but one that (also ?) accepts a pointer to the the device type. I didn't spend any time tracking down potential users, though, so I may be off track here.

I don't understand the problem, for USB we have different "types" of devices on the bus just fine. Or are you saying that the function you created isn't going to be used in the hwmon core in the end?

I doubt device_create() really needs to worry about different types, but I could be wrong :)

thanks,

greg k-h

#10 lore raw
Quoted 44 lines · Greg Kroah-Hartman
Quoted 18 lines · Guenter Roeck
Quoted 17 lines · Greg Kroah-Hartman

Hi all,

Guenter and Oliver have been pointing out a few limitations of the driver core's ability to create files properly (i.e. in a way that doesn't race with userspace.) The driver core allows this, but it doesn't export that ability to drivers very easily, and for binary files, not at all.

So here's a set of 6 patches that I'll be queueing up to go to Linus in time for 3.11 so that people can start using them in their driver subsystems. It adds some new macros to make using attributes and attribute groups easier, adds binary file capabilities to attribute groups, and finally, lets subsystems (like platform drivers) set a attribute group for when their device is created.

If anyone has any problems with these patches, please let me know.

Quoted 7 lines
Quoted 4 lines

Guenter, I've tweaked your original patch a bit, changing the name of the function and putting the kernel doc comments in the correct place so the build doesn't complain about it.

I like it - thanks a lot for picking that up. I think there are several drivers who could and should use the new API call (gpio, infiniband/umad, c2port, ptp, scsi/osst, android/timed_output, asus_oled are some examples).

Yes, I'll be sweeping the tree for the next few released doing all of this. The amount of sysfs "cruft" that has accumulated in the past few years since I last looked is crazy...

Quoted 8 lines

For hwmon, I ended up having to handle device creation internally after all. Reason is that I also had to set device->type to a new hwmon device type. That in turn was necessary to be able to support the hwmon 'name' attribute properly (it has to be optional, meaning I could not use class->dev_attrs but had to use device_type->groups instead). I hope I can send out a revised series of patches soon .. only I'll leave for pto next week and I am bugged down with other work right now, so it may have to wait until after I return.

Quoted 4 lines

Wonder if it would make sense to support a core driver API call for that purpose as well - ie one that not only has the additional groups argument, but one that (also ?) accepts a pointer to the the device type. I didn't spend any time tracking down potential users, though, so I may be off track here.

Quoted 7 lines

I don't understand the problem, for USB we have different "types" of devices on the bus just fine. Or are you saying that the function you created isn't going to be used in the hwmon core in the end?

I doubt device_create() really needs to worry about different types, but I could be wrong :)

All I needed was the dev_groups field you just added to the class structure. I am currently merging your patches into my code, so you'll get some free test coverage ...

Thanks,
Guenter

author maintainer
#11 lore raw

[PATCH 7/6] driver core: add default groups to struct class

In reply to Greg Kroah-Hartman

We should be using groups, not attribute lists, for classes to allow subdirectories, and soon, binary files. Groups are just more flexible overall, so add them.

The dev_attrs list will go away after all in-kernel users are converted to use dev_groups.

---
Forgot this one in the series, it adds support to classes for groups, so that we can handle binary attributes properly for them as well.

 drivers/base/core.c    |    8 +++++++-
 include/linux/device.h |    4 +++-
 2 files changed, 10 insertions(+), 2 deletions(-)
drivers/base/core.c +7 -1
@@ -528,9 +528,12 @@ static int device_add_attrs(struct devic
 	int error;
 
 	if (class) {
-		error = device_add_attributes(dev, class->dev_attrs);
+		error = device_add_groups(dev, class->dev_groups);
 		if (error)
 			return error;
+		error = device_add_attributes(dev, class->dev_attrs);
+		if (error)
+			goto err_remove_class_groups;
 		error = device_add_bin_attributes(dev, class->dev_bin_attrs);
 		if (error)
 			goto err_remove_class_attrs;
@@ -563,6 +566,9 @@ static int device_add_attrs(struct devic
  err_remove_class_attrs:
 	if (class)
 		device_remove_attributes(dev, class->dev_attrs);
+ err_remove_class_groups:
+	if (class)
+		device_remove_groups(dev, class->dev_groups);
 
 	return error;
 }
include/linux/device.h +3 -1
@@ -313,6 +313,7 @@ int subsys_virtual_register(struct bus_t
  * @name:	Name of the class.
  * @owner:	The module owner.
  * @class_attrs: Default attributes of this class.
+ * @dev_groups:	Default attributes of the devices that belong to the class.
  * @dev_attrs:	Default attributes of the devices belong to the class.
  * @dev_bin_attrs: Default binary attributes of the devices belong to the class.
  * @dev_kobj:	The kobject that represents this class and links it into the hierarchy.
@@ -342,7 +343,8 @@ struct class {
 	struct module		*owner;
 
 	struct class_attribute		*class_attrs;
-	struct device_attribute		*dev_attrs;
+	struct device_attribute		*dev_attrs;	/* use dev_groups instead */
+	const struct attribute_group	**dev_groups;
 	struct bin_attribute		*dev_bin_attrs;
 	struct kobject			*dev_kobj;
 
#12 lore raw

Re: [PATCH 7/6] driver core: add default groups to struct class

Quoted 9 lines · Greg Kroah-Hartman

We should be using groups, not attribute lists, for classes to allow subdirectories, and soon, binary files. Groups are just more flexible overall, so add them.

The dev_attrs list will go away after all in-kernel users are converted to use dev_groups.

Nice one ... that solves my problem.

Thanks!

Guenter

Quoted 55 lines

---
Forgot this one in the series, it adds support to classes for groups, so that we can handle binary attributes properly for them as well.

 drivers/base/core.c    |    8 +++++++-
 include/linux/device.h |    4 +++-
 2 files changed, 10 insertions(+), 2 deletions(-)
drivers/base/core.c +7 -1
@@ -528,9 +528,12 @@ static int device_add_attrs(struct devic
 	int error;
 
 	if (class) {
-		error = device_add_attributes(dev, class->dev_attrs);
+		error = device_add_groups(dev, class->dev_groups);
 		if (error)
 			return error;
+		error = device_add_attributes(dev, class->dev_attrs);
+		if (error)
+			goto err_remove_class_groups;
 		error = device_add_bin_attributes(dev, class->dev_bin_attrs);
 		if (error)
 			goto err_remove_class_attrs;
@@ -563,6 +566,9 @@ static int device_add_attrs(struct devic
  err_remove_class_attrs:
 	if (class)
 		device_remove_attributes(dev, class->dev_attrs);
+ err_remove_class_groups:
+	if (class)
+		device_remove_groups(dev, class->dev_groups);
 
 	return error;
 }
include/linux/device.h +3 -1
@@ -313,6 +313,7 @@ int subsys_virtual_register(struct bus_t
  * @name:	Name of the class.
  * @owner:	The module owner.
  * @class_attrs: Default attributes of this class.
+ * @dev_groups:	Default attributes of the devices that belong to the class.
  * @dev_attrs:	Default attributes of the devices belong to the class.
  * @dev_bin_attrs: Default binary attributes of the devices belong to the class.
  * @dev_kobj:	The kobject that represents this class and links it into the hierarchy.
@@ -342,7 +343,8 @@ struct class {
 	struct module		*owner;
 
 	struct class_attribute		*class_attrs;
-	struct device_attribute		*dev_attrs;
+	struct device_attribute		*dev_attrs;	/* use dev_groups instead */
+	const struct attribute_group	**dev_groups;
 	struct bin_attribute		*dev_bin_attrs;
 	struct kobject			*dev_kobj;
 
author maintainer
#13 lore raw

Re: [PATCH 7/6] driver core: add default groups to struct class

Quoted 6 lines · Guenter Roeck
Quoted 5 lines · Greg Kroah-Hartman

We should be using groups, not attribute lists, for classes to allow subdirectories, and soon, binary files. Groups are just more flexible overall, so add them.

Quoted 6 lines
Quoted 4 lines

The dev_attrs list will go away after all in-kernel users are converted to use dev_groups.

Nice one ... that solves my problem.

Thanks, I'll work on 'struct bus_type' next, moving that to only use groups, but that's not as important from what I can tell, busses don't seem to abuse sysfs as bad as drivers and devices do :)

thanks,

greg k-h

author maintainer
#14 lore raw

[PATCH 7/6 v2] driver core: add default groups to struct class

In reply to Greg Kroah-Hartman

We should be using groups, not attribute lists, for classes to allow subdirectories, and soon, binary files. Groups are just more flexible overall, so add them.

The dev_attrs list will go away after all in-kernel users are converted to use dev_groups.

---

v2: forgot to remove groups from classes when the device is removed, it
still worked fine, but it's nice to clean up things properly.

 drivers/base/core.c    |    9 ++++++++-
 include/linux/device.h |    4 +++-
 2 files changed, 11 insertions(+), 2 deletions(-)
drivers/base/core.c +8 -1
@@ -528,9 +528,12 @@ static int device_add_attrs(struct devic
 	int error;
 
 	if (class) {
-		error = device_add_attributes(dev, class->dev_attrs);
+		error = device_add_groups(dev, class->dev_groups);
 		if (error)
 			return error;
+		error = device_add_attributes(dev, class->dev_attrs);
+		if (error)
+			goto err_remove_class_groups;
 		error = device_add_bin_attributes(dev, class->dev_bin_attrs);
 		if (error)
 			goto err_remove_class_attrs;
@@ -563,6 +566,9 @@ static int device_add_attrs(struct devic
  err_remove_class_attrs:
 	if (class)
 		device_remove_attributes(dev, class->dev_attrs);
+ err_remove_class_groups:
+	if (class)
+		device_remove_groups(dev, class->dev_groups);
 
 	return error;
 }
@@ -581,6 +587,7 @@ static void device_remove_attrs(struct d
 	if (class) {
 		device_remove_attributes(dev, class->dev_attrs);
 		device_remove_bin_attributes(dev, class->dev_bin_attrs);
+		device_remove_groups(dev, class->dev_groups);
 	}
 }
 
include/linux/device.h +3 -1
@@ -313,6 +313,7 @@ int subsys_virtual_register(struct bus_t
  * @name:	Name of the class.
  * @owner:	The module owner.
  * @class_attrs: Default attributes of this class.
+ * @dev_groups:	Default attributes of the devices that belong to the class.
  * @dev_attrs:	Default attributes of the devices belong to the class.
  * @dev_bin_attrs: Default binary attributes of the devices belong to the class.
  * @dev_kobj:	The kobject that represents this class and links it into the hierarchy.
@@ -342,7 +343,8 @@ struct class {
 	struct module		*owner;
 
 	struct class_attribute		*class_attrs;
-	struct device_attribute		*dev_attrs;
+	struct device_attribute		*dev_attrs;	/* use dev_groups instead */
+	const struct attribute_group	**dev_groups;
 	struct bin_attribute		*dev_bin_attrs;
 	struct kobject			*dev_kobj;
 
author maintainer
#15 lore raw

v2 cover Driver core and sysfs changes for attribute groups

In reply to Greg Kroah-Hartman

Hi all,

Here's the second iteration of the patchset to add better attribute group support to the driver core and sysfs.

I've tested these (shocker!) and everything works fine with them (I'm sending this from Linus's latest kernel with these 7 on top of it.)

I'd like to send these to Linus for 3.11 unless someone objects.

Oliver, please use this series instead of the last one, it has fixes that Guenter pointed out that would have crashed your box at boot.

changes from v2:
- actually boots
- 7th patch added properly
- added BUS_ATTR, CLASS_ATTR, and DRIVER_ATTR RW and RO macros to help with converting code to use attributes properly.

thanks,

greg k-h

author maintainer
#16 lore raw

PATCH v2 1/7 sysfs.h: add __ATTR_RW() macro

A number of parts of the kernel created their own version of this, might as well have the sysfs core provide it instead.

---
 include/linux/sysfs.h | 2 ++
 kernel/events/core.c  | 2 --
 mm/backing-dev.c      | 2 --
 3 files changed, 2 insertions(+), 4 deletions(-)
include/linux/sysfs.h +2 -0
index e2cee22..9cd20c8 100644
@@ -79,6 +79,8 @@ struct attribute_group {
 	.show	= _name##_show,					\
 }
 
+#define __ATTR_RW(_name) __ATTR(_name, 0644, _name##_show, _name##_store)
+
 #define __ATTR_NULL { .attr = { .name = NULL } }
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
kernel/events/core.c +0 -2
index 1833bc5..95191bf 100644
@@ -6212,8 +6212,6 @@ perf_event_mux_interval_ms_store(struct device *dev,
 	return count;
 }
 
-#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
-
 static struct device_attribute pmu_dev_attrs[] = {
 	__ATTR_RO(type),
 	__ATTR_RW(perf_event_mux_interval_ms),
mm/backing-dev.c +0 -2
index d014ee5..e04454c 100644
@@ -232,8 +232,6 @@ static ssize_t stable_pages_required_show(struct device *dev,
 			bdi_cap_stable_pages_required(bdi) ? 1 : 0);
 }
 
-#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
-
 static struct device_attribute bdi_dev_attrs[] = {
 	__ATTR_RW(read_ahead_kb),
 	__ATTR_RW(min_ratio),
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
author maintainer
#17 lore raw

PATCH v2 2/7 sysfs.h: add ATTRIBUTE_GROUPS() macro

In reply to Greg Kroah-Hartman

To make it easier for driver subsystems to work with attribute groups, create the ATTRIBUTE_GROUPS macro to remove some of the repetitive typing for the most common use for attribute groups.

---
 include/linux/sysfs.h | 9 +++++++++
 1 file changed, 9 insertions(+)
include/linux/sysfs.h +9 -0
index 9cd20c8..f62ff01 100644
@@ -94,6 +94,15 @@ struct attribute_group {
 #define __ATTR_IGNORE_LOCKDEP	__ATTR
 #endif
 
+#define ATTRIBUTE_GROUPS(name)					\
+static const struct attribute_group name##_group = {		\
+	.attrs = name##_attrs,					\
+};								\
+static const struct attribute_group *name##_groups[] = {	\
+	&name##_group,						\
+	NULL,							\
+}
+
 #define attr_name(_attr) (_attr).attr.name
 
 struct file;
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
#18 lore raw

Re: [PATCH v2 2/7] sysfs.h: add ATTRIBUTE_GROUPS() macro

Quoted 3 lines · Greg Kroah-Hartman

To make it easier for driver subsystems to work with attribute groups, create the ATTRIBUTE_GROUPS macro to remove some of the repetitive typing for the most common use for attribute groups.

But binary groups are discriminated against :(

The attached patch should help here.

I suppose one more additional helper wouldn't be bad to have:

#define ATTRIBUTE_(BIN_)GROUPS_R[O/W](_name(, _size)) \
ATTRIBUTE_(BIN_)ATTR_R[O/W](_name, _size); \
ATTRIBUTE_(BIN_)GROUPS(_name)

but wasn't sure if that wasn't a little overkill. I gladly add it in an additional patch.

Quoted 28 lines
---
  include/linux/sysfs.h | 9 +++++++++
  1 file changed, 9 insertions(+)
include/linux/sysfs.h +9 -0
index 9cd20c8..f62ff01 100644
@@ -94,6 +94,15 @@ struct attribute_group {
  #define __ATTR_IGNORE_LOCKDEP	__ATTR
  #endif
 
+#define ATTRIBUTE_GROUPS(name)					\
+static const struct attribute_group name##_group = {		\
+	.attrs = name##_attrs,					\
+};								\
+static const struct attribute_group *name##_groups[] = {	\
+	&name##_group,						\
+	NULL,							\
+}
+
  #define attr_name(_attr) (_attr).attr.name
 
  struct file;
Quoted 1 line

From 003ab7a74ff689daa6934e7bc50c498b2d35a1cc Mon Sep 17 00:00:00 2001

From: Oliver Schinagl <[email protected]>
Date: Thu, 11 Jul 2013 13:48:18 +0200
Subject: [PATCH] sysfs: add more helper macro's for (bin_)attribute(_groups)

With the recent changes to sysfs there's various helper macro's. However there's no RW, RO BIN_ helper macro's. This patch adds them.

Additionally there are no BIN_ group helpers so there's that aswell Moreso, if both bin and normal attribute groups are used, there's a simple helper for that, though the naming code be better. _TXT_ for the show/store ones and neither TXT or BIN for both, but that would change things to extensivly.

Finally there's also helpers for ATTRIBUTE_ATTRS.

After this patch, create default attributes can be as easy as:

ATTRIBUTE_(BIN_)ATTR_RO(name, SIZE);
ATTRIBUTE_BIN_GROUPS(name);

---
 include/linux/sysfs.h | 96 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 84 insertions(+), 12 deletions(-)
include/linux/sysfs.h +84 -12
index 2c3b6a3..0ebed11 100644
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/lockdep.h>
 #include <linux/kobject_ns.h>
+#include <linux/stat.h>
 #include <linux/atomic.h>
 
 struct kobject;
@@ -94,15 +95,32 @@ struct attribute_group {
 #define __ATTR_IGNORE_LOCKDEP	__ATTR
 #endif
 
-#define ATTRIBUTE_GROUPS(name)					\
-static const struct attribute_group name##_group = {		\
-	.attrs = name##_attrs,					\
+#define __ATTRIBUTE_GROUPS(_name)				\
+static const struct attribute_group *_name##_groups[] = {	\
+	&_name##_group,						\
+	NULL,							\
+}
+
+#define ATTRIBUTE_GROUPS(_name)					\
+static const struct attribute_group _name##_group = {		\
+	.attrs = _name##_attrs,					\
 };								\
-static const struct attribute_group *name##_groups[] = {	\
-	&name##_group,						\
+__ATTRIBUTE_GROUPS(_name)
+
+#define __ATTRIBUTE_ATTRS(_name)				\
+struct bin_attribute *_name##_attrs[] = {			\
+	&_name##_attr,						\
 	NULL,							\
 }
 
+#define ATTRIBUTE_ATTR_RO(_name, _size)				\
+struct attribute _name##_attr = __ATTR_RO(_name, _size);	\
+__ATTRIBUTE_ATTRS(_name)
+
+#define ATTRIBUTE_ATTR_RW(_name, _size)				\
+struct attribute _name##_attr = __ATTR_RW(_name, _size);	\
+__ATTRIBUTE_ATTRS(_name)
+
 #define attr_name(_attr) (_attr).attr.name
 
 struct file;
@@ -132,15 +150,69 @@ struct bin_attribute {
  */
 #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
 
-/* macro to create static binary attributes easier */
-#define BIN_ATTR(_name, _mode, _read, _write, _size)		\
-struct bin_attribute bin_attr_##_name = {			\
-	.attr = {.name = __stringify(_name), .mode = _mode },	\
-	.read	= _read,					\
-	.write	= _write,					\
-	.size	= _size,					\
+/* macros to create static binary attributes easier */
+#define __BIN_ATTR(_name, _mode, _read, _write, _size) {		\
+	.attr = { .name = __stringify(_name), .mode = _mode },		\
+	.read	= _read,						\
+	.write	= _write,						\
+	.size	= _size,						\
+}
+
+#define __BIN_ATTR_RO(_name, _size) {					\
+	.attr	= { .name = __stringify(_name), .mode = S_IRUGO },	\
+	.read	= _name##_read,						\
+	.size	= _size,						\
+}
+
+#define __BIN_ATTR_RW(_name, _size) __BIN_ATTR(_name,			\
+				   (S_IWUSR | S_IRUGO), _name##_read,	\
+				   _name##_write)
+
+#define __BIN_ATTR_NULL __ATTR_NULL
+
+#define BIN_ATTR(_name, _mode, _read, _write, _size)			\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR(_name, _mode, _read,	\
+					_write, _size)
+
+#define BIN_RO_ATTR(_name, _size)					\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR_RO(_name, _size)
+
+#define BIN_RW_ATTR(_name, _size)					\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size)
+
+#define __ATTRIBUTE_BIN_GROUPS(_name)					\
+static const struct attribute_group *_name##_bin_groups[] = {		\
+	&_name##_bin_group,						\
+	NULL,								\
 }
 
+#define ATTRIBUTE_BIN_GROUPS(_name)					\
+static const struct attribute_group _name##_bin_group = {		\
+	.bin_attrs = _name##_bin_attrs,					\
+};									\
+__ATTRIBUTE_BIN_GROUPS(_name)
+
+#define ATTRIBUTE_FULL_GROUPS(_name)					\
+static const struct attribute_group _name##_full_group = {		\
+	.attrs = _name##_attrs,						\
+	.bin_attrs = _name##_bin_attrs,					\
+};									\
+__ATTRIBUTE_GROUPS(_name); __ATTRIBUTE_BIN_GROUPS(_name)
+
+#define __ATTRIBUTE_BIN_ATTRS(_name)					\
+struct bin_attribute *_name##_bin_attrs[] = {				\
+	&_name##_bin_attr,						\
+	NULL,								\
+}
+
+#define ATTRIBUTE_BIN_ATTR_RO(_name, _size)				\
+struct bin_attribute _name##_bin_attr = __BIN_ATTR_RO(_name, _size);	\
+__ATTRIBUTE_BIN_ATTRS(_name)
+
+#define ATTRIBUTE_BIN_ATTR_RW(_name, _size)				\
+struct bin_attribute _name##_bin_attr = __BIN_ATTR_RW(_name, _size);	\
+__ATTRIBUTE_BIN_ATTRS(_name)
+
 struct sysfs_ops {
 	ssize_t	(*show)(struct kobject *, struct attribute *,char *);
 	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
Signature · 1 line
1.8.1.5
author maintainer
#19 lore raw

Re: [PATCH v2 2/7] sysfs.h: add ATTRIBUTE_GROUPS() macro

Quoted 5 lines · Oliver Schinagl
Quoted 3 lines · Greg Kroah-Hartman

To make it easier for driver subsystems to work with attribute groups, create the ATTRIBUTE_GROUPS macro to remove some of the repetitive typing for the most common use for attribute groups.

But binary groups are discriminated against :(

Yes, as they are "rarer" by far, as they should be. binary sysfs files should almost never be used, as they are only "pass-through" files to the hardware, so I want to see you do more work in order to use them, as they should not be created lightly.

Quoted 1 line

The attached patch should help here.

Can you give me an example of using these macros? I seem to be lost in them somehow, or maybe my morning coffee just hasn't kicked in...

Quoted 5 lines

I suppose one more additional helper wouldn't be bad to have:

#define ATTRIBUTE_(BIN_)GROUPS_R[O/W](_name(, _size)) \
ATTRIBUTE_(BIN_)ATTR_R[O/W](_name, _size); \
ATTRIBUTE_(BIN_)GROUPS(_name)

Would that ever be needed?

Quoted 62 lines
Quoted 1 line

From 003ab7a74ff689daa6934e7bc50c498b2d35a1cc Mon Sep 17 00:00:00 2001

From: Oliver Schinagl <[email protected]>
Date: Thu, 11 Jul 2013 13:48:18 +0200
Subject: [PATCH] sysfs: add more helper macro's for (bin_)attribute(_groups)

With the recent changes to sysfs there's various helper macro's. However there's no RW, RO BIN_ helper macro's. This patch adds them.

Additionally there are no BIN_ group helpers so there's that aswell Moreso, if both bin and normal attribute groups are used, there's a simple helper for that, though the naming code be better. _TXT_ for the show/store ones and neither TXT or BIN for both, but that would change things to extensivly.

Finally there's also helpers for ATTRIBUTE_ATTRS.

After this patch, create default attributes can be as easy as:

ATTRIBUTE_(BIN_)ATTR_RO(name, SIZE);
ATTRIBUTE_BIN_GROUPS(name);

---
 include/linux/sysfs.h | 96 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 84 insertions(+), 12 deletions(-)
include/linux/sysfs.h +15 -5
index 2c3b6a3..0ebed11 100644
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/lockdep.h>
 #include <linux/kobject_ns.h>
+#include <linux/stat.h>
 #include <linux/atomic.h>
 
 struct kobject;
@@ -94,15 +95,32 @@ struct attribute_group {
 #define __ATTR_IGNORE_LOCKDEP	__ATTR
 #endif
 
-#define ATTRIBUTE_GROUPS(name)					\
-static const struct attribute_group name##_group = {		\
-	.attrs = name##_attrs,					\
+#define __ATTRIBUTE_GROUPS(_name)				\
+static const struct attribute_group *_name##_groups[] = {	\
+	&_name##_group,						\
+	NULL,							\
+}
+
+#define ATTRIBUTE_GROUPS(_name)					\
+static const struct attribute_group _name##_group = {		\
+	.attrs = _name##_attrs,					\
 };								\
-static const struct attribute_group *name##_groups[] = {	\
-	&name##_group,						\
+__ATTRIBUTE_GROUPS(_name)
+
+#define __ATTRIBUTE_ATTRS(_name)				\
+struct bin_attribute *_name##_attrs[] = {			\
+	&_name##_attr,						\

include/linux/sysfs.h struct attribute_group { · line 122

Quoted 10 lines
include/linux/sysfs.h +7 -0
 	NULL,							\
 }
 
+#define ATTRIBUTE_ATTR_RO(_name, _size)				\
+struct attribute _name##_attr = __ATTR_RO(_name, _size);	\
+__ATTRIBUTE_ATTRS(_name)
+
+#define ATTRIBUTE_ATTR_RW(_name, _size)				\
+struct attribute _name##_attr = __ATTR_RW(_name, _size);	\
+__ATTRIBUTE_ATTRS(_name)

What do these two help out with? "attribute attribute read-write" seems a bit "clunky", don't you think? :)

Quoted 34 lines
include/linux/sysfs.h +20 -7
+
 #define attr_name(_attr) (_attr).attr.name
 
 struct file;
@@ -132,15 +150,69 @@ struct bin_attribute {
  */
 #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
 
-/* macro to create static binary attributes easier */
-#define BIN_ATTR(_name, _mode, _read, _write, _size)		\
-struct bin_attribute bin_attr_##_name = {			\
-	.attr = {.name = __stringify(_name), .mode = _mode },	\
-	.read	= _read,					\
-	.write	= _write,					\
-	.size	= _size,					\
+/* macros to create static binary attributes easier */
+#define __BIN_ATTR(_name, _mode, _read, _write, _size) {		\
+	.attr = { .name = __stringify(_name), .mode = _mode },		\
+	.read	= _read,						\
+	.write	= _write,						\
+	.size	= _size,						\
+}
+
+#define __BIN_ATTR_RO(_name, _size) {					\
+	.attr	= { .name = __stringify(_name), .mode = S_IRUGO },	\
+	.read	= _name##_read,						\
+	.size	= _size,						\
+}
+
+#define __BIN_ATTR_RW(_name, _size) __BIN_ATTR(_name,			\
+				   (S_IWUSR | S_IRUGO), _name##_read,	\
+				   _name##_write)
+
+#define __BIN_ATTR_NULL __ATTR_NULL

include/linux/sysfs.h struct bin_attribute { · line 181

Quoted 10 lines
include/linux/sysfs.h +10 -0
+
+#define BIN_ATTR(_name, _mode, _read, _write, _size)			\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR(_name, _mode, _read,	\
+					_write, _size)
+
+#define BIN_RO_ATTR(_name, _size)					\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR_RO(_name, _size)
+
+#define BIN_RW_ATTR(_name, _size)					\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size)

To be consistent, these shoudl be BIN_ATTR_RO and BIN_ATTR_RW, right?

These all look fine to me, thanks.

It's these that I'm confused about:

Quoted 23 lines
include/linux/sysfs.h +21 -0
+
+#define __ATTRIBUTE_BIN_GROUPS(_name)					\
+static const struct attribute_group *_name##_bin_groups[] = {		\
+	&_name##_bin_group,						\
+	NULL,								\
 }
 
+#define ATTRIBUTE_BIN_GROUPS(_name)					\
+static const struct attribute_group _name##_bin_group = {		\
+	.bin_attrs = _name##_bin_attrs,					\
+};									\
+__ATTRIBUTE_BIN_GROUPS(_name)
+
+#define ATTRIBUTE_FULL_GROUPS(_name)					\
+static const struct attribute_group _name##_full_group = {		\
+	.attrs = _name##_attrs,						\
+	.bin_attrs = _name##_bin_attrs,					\
+};									\
+__ATTRIBUTE_GROUPS(_name); __ATTRIBUTE_BIN_GROUPS(_name)
+
+#define __ATTRIBUTE_BIN_ATTRS(_name)					\
+struct bin_attribute *_name##_bin_attrs[] = {				\
+	&_name##_bin_attr,						\

include/linux/sysfs.h struct bin_attribute { · line 214

Quoted 10 lines
include/linux/sysfs.h +10 -0
+	NULL,								\
+}
+
+#define ATTRIBUTE_BIN_ATTR_RO(_name, _size)				\
+struct bin_attribute _name##_bin_attr = __BIN_ATTR_RO(_name, _size);	\
+__ATTRIBUTE_BIN_ATTRS(_name)
+
+#define ATTRIBUTE_BIN_ATTR_RW(_name, _size)				\
+struct bin_attribute _name##_bin_attr = __BIN_ATTR_RW(_name, _size);	\
+__ATTRIBUTE_BIN_ATTRS(_name)

Can you show me how these would be used in a real-world example?

thanks,

greg k-h

#20 lore raw

Re: [PATCH v2 2/7] sysfs.h: add ATTRIBUTE_GROUPS() macro

Quoted 11 lines · Greg Kroah-Hartman
Quoted 5 lines · Oliver Schinagl
Quoted 3 lines · Greg Kroah-Hartman

To make it easier for driver subsystems to work with attribute groups, create the ATTRIBUTE_GROUPS macro to remove some of the repetitive typing for the most common use for attribute groups.

But binary groups are discriminated against :(

Yes, as they are "rarer" by far, as they should be. binary sysfs files should almost never be used, as they are only "pass-through" files to the hardware, so I want to see you do more work in order to use them, as they should not be created lightly.

I guess I can see a valid reason here, but they are only helper macro's making life easier for people who do need to use these and are on par with the non-binary versions. And we already have quite some binary attributes, probably far less then normal ones :)

Anyway, wouldn't all users be reviewed anyway? But I guess it's a small safety net to make it not TOO easy.

Quoted 5 lines
Quoted 2 lines

The attached patch should help here.

Can you give me an example of using these macros? I seem to be lost in them somehow, or maybe my morning coffee just hasn't kicked in...

Yeah, I kinda added the whole shebang there :) I was trying being helpful :(

Quoted 8 lines
Quoted 6 lines

I suppose one more additional helper wouldn't be bad to have:

#define ATTRIBUTE_(BIN_)GROUPS_R[O/W](_name(, _size)) \
ATTRIBUTE_(BIN_)ATTR_R[O/W](_name, _size); \
ATTRIBUTE_(BIN_)GROUPS(_name)

Would that ever be needed?

Of ourse, by the lazy :)

I think now you create an attribute in a group as this (with this patch):

ATTRIBUTE_ATTR_RO(name, SIZE);
ATTRIBUTE_GROUPS(name);

.group = name;

After that last addition, you'd simply do:
ATTRIBUTE_GROUPS_RO(name);

.group = name;

saves a whole line :)

Quoted 54 lines
Quoted 54 lines
Quoted 2 lines

From 003ab7a74ff689daa6934e7bc50c498b2d35a1cc Mon Sep 17 00:00:00 2001

From: Oliver Schinagl <[email protected]>
Date: Thu, 11 Jul 2013 13:48:18 +0200
Subject: [PATCH] sysfs: add more helper macro's for (bin_)attribute(_groups)

With the recent changes to sysfs there's various helper macro's. However there's no RW, RO BIN_ helper macro's. This patch adds them.

Additionally there are no BIN_ group helpers so there's that aswell Moreso, if both bin and normal attribute groups are used, there's a simple helper for that, though the naming code be better. _TXT_ for the show/store ones and neither TXT or BIN for both, but that would change things to extensivly.

Finally there's also helpers for ATTRIBUTE_ATTRS.

After this patch, create default attributes can be as easy as:

ATTRIBUTE_(BIN_)ATTR_RO(name, SIZE);
ATTRIBUTE_BIN_GROUPS(name);

---
  include/linux/sysfs.h | 96 ++++++++++++++++++++++++++++++++++++++++++++-------
  1 file changed, 84 insertions(+), 12 deletions(-)
include/linux/sysfs.h +9 -3
index 2c3b6a3..0ebed11 100644
@@ -17,6 +17,7 @@
  #include <linux/list.h>
  #include <linux/lockdep.h>
  #include <linux/kobject_ns.h>
+#include <linux/stat.h>
  #include <linux/atomic.h>
 
  struct kobject;
@@ -94,15 +95,32 @@ struct attribute_group {
  #define __ATTR_IGNORE_LOCKDEP	__ATTR
  #endif
 
-#define ATTRIBUTE_GROUPS(name)					\
-static const struct attribute_group name##_group = {		\
-	.attrs = name##_attrs,					\
+#define __ATTRIBUTE_GROUPS(_name)				\
+static const struct attribute_group *_name##_groups[] = {	\
+	&_name##_group,						\
+	NULL,							\
+}
+
+#define ATTRIBUTE_GROUPS(_name)					\
+static const struct attribute_group _name##_group = {		\
Quoted 8 lines

include/linux/sysfs.h struct attribute_group { · line 111

Quoted 8 lines
include/linux/sysfs.h +5 -2
+	.attrs = _name##_attrs,					\
  };								\
-static const struct attribute_group *name##_groups[] = {	\
-	&name##_group,						\
+__ATTRIBUTE_GROUPS(_name)
+
+#define __ATTRIBUTE_ATTRS(_name)				\
+struct bin_attribute *_name##_attrs[] = {			\

typo here, scrap bin_ copy paste fail!

Quoted 4 lines
Quoted 4 lines
include/linux/sysfs.h +1 -0
+	&_name##_attr,						\
  	NULL,							\
  }
 
Quoted 10 lines

include/linux/sysfs.h struct attribute_group { · line 122

Quoted 7 lines
include/linux/sysfs.h +7 -0
+#define ATTRIBUTE_ATTR_RO(_name, _size)				\
+struct attribute _name##_attr = __ATTR_RO(_name, _size);	\
+__ATTRIBUTE_ATTRS(_name)
+
+#define ATTRIBUTE_ATTR_RW(_name, _size)				\
+struct attribute _name##_attr = __ATTR_RW(_name, _size);	\
+__ATTRIBUTE_ATTRS(_name)

What do these two help out with? "attribute attribute read-write" seems a bit "clunky", don't you think? :)

I aggree, but I tried to stick with the ATTRIBUTE_GROUP naming and that's the best I could come up with.

Unless I completely misunderstood (which isn't all that unlikely) the following is needed to create a group using a .group.

So you pass group an array of attribute_group pointers. The ATTRIBUTE_GROUPS helps there, right? It saves the typing of creating the array of groups and adding groups to that.

So a group consists of an array of attributes if I understood right and that array needs to be filled with pointers attributes? well those ATTRIBUTE_ATTR's do just that. Granted, maybe the naming is poor, but just ATTRS() felt to short.

Quoted 39 lines
Quoted 39 lines
include/linux/sysfs.h +24 -7
+
  #define attr_name(_attr) (_attr).attr.name
 
  struct file;
@@ -132,15 +150,69 @@ struct bin_attribute {
   */
  #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
 
-/* macro to create static binary attributes easier */
-#define BIN_ATTR(_name, _mode, _read, _write, _size)		\
-struct bin_attribute bin_attr_##_name = {			\
-	.attr = {.name = __stringify(_name), .mode = _mode },	\
-	.read	= _read,					\
-	.write	= _write,					\
-	.size	= _size,					\
+/* macros to create static binary attributes easier */
+#define __BIN_ATTR(_name, _mode, _read, _write, _size) {		\
+	.attr = { .name = __stringify(_name), .mode = _mode },		\
+	.read	= _read,						\
+	.write	= _write,						\
+	.size	= _size,						\
+}
+
+#define __BIN_ATTR_RO(_name, _size) {					\
+	.attr	= { .name = __stringify(_name), .mode = S_IRUGO },	\
+	.read	= _name##_read,						\
+	.size	= _size,						\
+}
+
+#define __BIN_ATTR_RW(_name, _size) __BIN_ATTR(_name,			\
+				   (S_IWUSR | S_IRUGO), _name##_read,	\
+				   _name##_write)
+
+#define __BIN_ATTR_NULL __ATTR_NULL
+
+#define BIN_ATTR(_name, _mode, _read, _write, _size)			\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR(_name, _mode, _read,	\
+					_write, _size)
Quoted 8 lines

include/linux/sysfs.h struct bin_attribute { · line 181

Quoted 6 lines
include/linux/sysfs.h +6 -0
+
+#define BIN_RO_ATTR(_name, _size)					\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR_RO(_name, _size)
+
+#define BIN_RW_ATTR(_name, _size)					\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size)

To be consistent, these shoudl be BIN_ATTR_RO and BIN_ATTR_RW, right?

Yes, I too did this before morning coffee, and I don't drink coffee!

Quoted 11 lines

These all look fine to me, thanks.

It's these that I'm confused about:

include/linux/sysfs.h struct bin_attribute { · line 187

Quoted 6 lines
include/linux/sysfs.h +5 -0
+
+#define __ATTRIBUTE_BIN_GROUPS(_name)					\
+static const struct attribute_group *_name##_bin_groups[] = {		\
+	&_name##_bin_group,						\
+	NULL,								\
  }

This is just a helper for the ones below.

Quoted 6 lines

include/linux/sysfs.h struct bin_attribute { · line 193

Quoted 6 lines
include/linux/sysfs.h +5 -0
+#define ATTRIBUTE_BIN_GROUPS(_name)					\
+static const struct attribute_group _name##_bin_group = {		\
+	.bin_attrs = _name##_bin_attrs,					\
+};									\
+__ATTRIBUTE_BIN_GROUPS(_name)

This is the equiv. of ATTRIBUTE_GROUPS(_name) which creates an attribute group, with only a binary attribute instead.

Quoted 7 lines

include/linux/sysfs.h struct bin_attribute { · line 200

Quoted 7 lines
include/linux/sysfs.h +7 -0
+
+#define ATTRIBUTE_FULL_GROUPS(_name)					\
+static const struct attribute_group _name##_full_group = {		\
+	.attrs = _name##_attrs,						\
+	.bin_attrs = _name##_bin_attrs,					\
+};									\
+__ATTRIBUTE_GROUPS(_name); __ATTRIBUTE_BIN_GROUPS(_name)

This one probably should go, it defines both, and since binaries should be used cautiously, it's not really needed I guess.

Quoted 6 lines

include/linux/sysfs.h struct bin_attribute { · line 206

Quoted 6 lines
include/linux/sysfs.h +6 -0
+
+#define __ATTRIBUTE_BIN_ATTRS(_name)					\
+struct bin_attribute *_name##_bin_attrs[] = {				\
+	&_name##_bin_attr,						\
+	NULL,								\
+}

Helper macro again for below

Quoted 8 lines

include/linux/sysfs.h struct bin_attribute { · line 214

Quoted 8 lines
include/linux/sysfs.h +8 -0
+
+#define ATTRIBUTE_BIN_ATTR_RO(_name, _size)				\
+struct bin_attribute _name##_bin_attr = __BIN_ATTR_RO(_name, _size);	\
+__ATTRIBUTE_BIN_ATTRS(_name)
+
+#define ATTRIBUTE_BIN_ATTR_RW(_name, _size)				\
+struct bin_attribute _name##_bin_attr = __BIN_ATTR_RW(_name, _size);	\
+__ATTRIBUTE_BIN_ATTRS(_name)

These I guess are the equivialent what ATTRIBUTE_GROUP is for groups, but now for the attributes that go in groups?

Quoted 2 lines

Can you show me how these would be used in a real-world example?

Well my real world is currently limited by my own driver. If I may copy paste from there:

ATTRIBUTE_BIN_ATTR_RO(sunxi_sid, SID_SIZE);
ATTRIBUTE_BIN_GROUPS(sunxi_sid);

static struct platform_driver sunxi_sid_driver = {
.probe = sunxi_sid_probe,
.remove = sunxi_sid_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE, .of_match_table = sunxi_sid_of_match, .groups = sunxi_sid_bin_groups,
},
};
module_platform_driver(sunxi_sid_driver);

But if you say, you want to be a little less complete, we can drop ATTRIBUTE_BIN_ATTR_R[OW]() forcing you to do this instead:

struct bin_attribute sunxi_sid_bin_attr = __BIN_ATTR_RO(eeprom, SID_SIZE);

struct bin_attribute *sunxi_sid_bin_attrs[] = {
&sunxi_sid_bin_attr,
NULL,
};

Which requires some manual labor yet still has the __BIN_ATTR_R[OW] macro's to help with some of the more tedious work and allowing you to name the binary attributes nicer?

Quoted 2 lines

thanks,

Sorry if I sound a little confusing, it made a lot of sense this morning :(

Oliver

Quoted 3 lines

greg k-h

author maintainer
#21 lore raw

Re: [PATCH v2 2/7] sysfs.h: add ATTRIBUTE_GROUPS() macro

Quoted 8 lines · Oliver Schinagl
Quoted 7 lines · Greg Kroah-Hartman
Quoted 5 lines · Oliver Schinagl
Quoted 3 lines · Greg Kroah-Hartman

To make it easier for driver subsystems to work with attribute groups, create the ATTRIBUTE_GROUPS macro to remove some of the repetitive typing for the most common use for attribute groups.

But binary groups are discriminated against :(

Quoted 8 lines
Quoted 4 lines

Yes, as they are "rarer" by far, as they should be. binary sysfs files should almost never be used, as they are only "pass-through" files to the hardware, so I want to see you do more work in order to use them, as they should not be created lightly.

I guess I can see a valid reason here, but they are only helper macro's making life easier for people who do need to use these and are on par with the non-binary versions. And we already have quite some binary attributes, probably far less then normal ones :)

I only count about 100 valid binary files in the tree at the moment, that's not really all that many to handle.

Quoted 2 lines

Anyway, wouldn't all users be reviewed anyway? But I guess it's a small safety net to make it not TOO easy.

exactly :)

Quoted 13 lines
Quoted 4 lines
Quoted 1 line

The attached patch should help here.

Can you give me an example of using these macros? I seem to be lost in them somehow, or maybe my morning coffee just hasn't kicked in...

Yeah, I kinda added the whole shebang there :) I was trying being helpful :(

Quoted 7 lines
Quoted 6 lines

I suppose one more additional helper wouldn't be bad to have:

#define ATTRIBUTE_(BIN_)GROUPS_R[O/W](_name(, _size)) \
ATTRIBUTE_(BIN_)ATTR_R[O/W](_name, _size); \
ATTRIBUTE_(BIN_)GROUPS(_name)

Quoted 6 lines
Quoted 1 line

Would that ever be needed?

Of ourse, by the lazy :)

I think now you create an attribute in a group as this (with this patch):

ATTRIBUTE_ATTR_RO(name, SIZE);

but "raw" attributes are rare, you really want a "device", "class", or "bus" attribute, right?

Quoted 10 lines

ATTRIBUTE_GROUPS(name);

.group = name;

After that last addition, you'd simply do:
ATTRIBUTE_GROUPS_RO(name);

.group = name;

saves a whole line :)

Not worth it :)

Quoted 83 lines
Quoted 53 lines
Quoted 53 lines
Quoted 1 line

From 003ab7a74ff689daa6934e7bc50c498b2d35a1cc Mon Sep 17 00:00:00 2001

From: Oliver Schinagl <[email protected]>
Date: Thu, 11 Jul 2013 13:48:18 +0200
Subject: [PATCH] sysfs: add more helper macro's for (bin_)attribute(_groups)

With the recent changes to sysfs there's various helper macro's. However there's no RW, RO BIN_ helper macro's. This patch adds them.

Additionally there are no BIN_ group helpers so there's that aswell Moreso, if both bin and normal attribute groups are used, there's a simple helper for that, though the naming code be better. _TXT_ for the show/store ones and neither TXT or BIN for both, but that would change things to extensivly.

Finally there's also helpers for ATTRIBUTE_ATTRS.

After this patch, create default attributes can be as easy as:

ATTRIBUTE_(BIN_)ATTR_RO(name, SIZE);
ATTRIBUTE_BIN_GROUPS(name);

---
 include/linux/sysfs.h | 96 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 84 insertions(+), 12 deletions(-)
include/linux/sysfs.h +9 -3
index 2c3b6a3..0ebed11 100644
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/lockdep.h>
 #include <linux/kobject_ns.h>
+#include <linux/stat.h>
 #include <linux/atomic.h>
 
 struct kobject;
@@ -94,15 +95,32 @@ struct attribute_group {
 #define __ATTR_IGNORE_LOCKDEP	__ATTR
 #endif
 
-#define ATTRIBUTE_GROUPS(name)					\
-static const struct attribute_group name##_group = {		\
-	.attrs = name##_attrs,					\
+#define __ATTRIBUTE_GROUPS(_name)				\
+static const struct attribute_group *_name##_groups[] = {	\
+	&_name##_group,						\
+	NULL,							\
+}
+
+#define ATTRIBUTE_GROUPS(_name)					\
+static const struct attribute_group _name##_group = {		\
Quoted 8 lines

include/linux/sysfs.h struct attribute_group { · line 111

Quoted 8 lines
include/linux/sysfs.h +5 -2
+	.attrs = _name##_attrs,					\
 };								\
-static const struct attribute_group *name##_groups[] = {	\
-	&name##_group,						\
+__ATTRIBUTE_GROUPS(_name)
+
+#define __ATTRIBUTE_ATTRS(_name)				\
+struct bin_attribute *_name##_attrs[] = {			\

typo here, scrap bin_ copy paste fail!

Quoted 4 lines
Quoted 4 lines
include/linux/sysfs.h +1 -0
+	&_name##_attr,						\
 	NULL,							\
 }
 
Quoted 10 lines

include/linux/sysfs.h struct attribute_group { · line 122

Quoted 7 lines
include/linux/sysfs.h +7 -0
+#define ATTRIBUTE_ATTR_RO(_name, _size)				\
+struct attribute _name##_attr = __ATTR_RO(_name, _size);	\
+__ATTRIBUTE_ATTRS(_name)
+
+#define ATTRIBUTE_ATTR_RW(_name, _size)				\
+struct attribute _name##_attr = __ATTR_RW(_name, _size);	\
+__ATTRIBUTE_ATTRS(_name)

What do these two help out with? "attribute attribute read-write" seems a bit "clunky", don't you think? :)

I aggree, but I tried to stick with the ATTRIBUTE_GROUP naming and that's the best I could come up with.

Unless I completely misunderstood (which isn't all that unlikely) the following is needed to create a group using a .group.

Quoted 8 lines

So you pass group an array of attribute_group pointers. The ATTRIBUTE_GROUPS helps there, right? It saves the typing of creating the array of groups and adding groups to that.

So a group consists of an array of attributes if I understood right and that array needs to be filled with pointers attributes? well those ATTRIBUTE_ATTR's do just that. Granted, maybe the naming is poor, but just ATTRS() felt to short.

Here's an example of a file I converted to use the ATTRIBUTE_GROUP() macro attached below (net/wireless/sysfs). As is, it's an increase of only 2 lines to the file overall, which is about normal for the conversion. As you can see, you still need a list of attributes (which someone has already said I need another macro for, to stop typing "&dev_attr*.attr" all the time).

With your macros, how would a file be converted to use them? Perhaps that will help explain things to me better.

Quoted 7 lines
Quoted 5 lines

include/linux/sysfs.h struct bin_attribute { · line 193

Quoted 5 lines
include/linux/sysfs.h +5 -0
+#define ATTRIBUTE_BIN_GROUPS(_name)					\
+static const struct attribute_group _name##_bin_group = {		\
+	.bin_attrs = _name##_bin_attrs,					\
+};									\
+__ATTRIBUTE_BIN_GROUPS(_name)

This is the equiv. of ATTRIBUTE_GROUPS(_name) which creates an attribute group, with only a binary attribute instead.

Again, binary files are rare, and should be rare, don't make it too easy to create them :)

Quoted 31 lines
Quoted 3 lines

include/linux/sysfs.h struct bin_attribute { · line 214

Quoted 3 lines
include/linux/sysfs.h +3 -0
+#define ATTRIBUTE_BIN_ATTR_RW(_name, _size)				\
+struct bin_attribute _name##_bin_attr = __BIN_ATTR_RW(_name, _size);	\
+__ATTRIBUTE_BIN_ATTRS(_name)

These I guess are the equivialent what ATTRIBUTE_GROUP is for groups, but now for the attributes that go in groups?

Quoted 2 lines

Can you show me how these would be used in a real-world example?

Well my real world is currently limited by my own driver. If I may copy paste from there:

ATTRIBUTE_BIN_ATTR_RO(sunxi_sid, SID_SIZE);
ATTRIBUTE_BIN_GROUPS(sunxi_sid);

static struct platform_driver sunxi_sid_driver = {
.probe = sunxi_sid_probe,
.remove = sunxi_sid_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE, .of_match_table = sunxi_sid_of_match, .groups = sunxi_sid_bin_groups,
},
};
module_platform_driver(sunxi_sid_driver);

But if you say, you want to be a little less complete, we can drop ATTRIBUTE_BIN_ATTR_R[OW]() forcing you to do this instead:

struct bin_attribute sunxi_sid_bin_attr = __BIN_ATTR_RO(eeprom, SID_SIZE);

Quoted 8 lines

struct bin_attribute *sunxi_sid_bin_attrs[] = {
&sunxi_sid_bin_attr,
NULL,
};

Which requires some manual labor yet still has the __BIN_ATTR_R[OW] macro's to help with some of the more tedious work and allowing you to name the binary attributes nicer?

BIN_ATTR_RO() is fine, I'd stick with that for now, it's getting confusing enough as-is :)

thanks,

greg k-h

#22 lore raw

Re: [PATCH v2 2/7] sysfs.h: add ATTRIBUTE_GROUPS() macro

Quoted 13 lines · Greg Kroah-Hartman
Quoted 12 lines · Oliver Schinagl
Quoted 11 lines · Greg Kroah-Hartman
Quoted 5 lines · Oliver Schinagl
Quoted 3 lines · Greg Kroah-Hartman

To make it easier for driver subsystems to work with attribute groups, create the ATTRIBUTE_GROUPS macro to remove some of the repetitive typing for the most common use for attribute groups.

But binary groups are discriminated against :(

Yes, as they are "rarer" by far, as they should be. binary sysfs files should almost never be used, as they are only "pass-through" files to the hardware, so I want to see you do more work in order to use them, as they should not be created lightly.

Quoted 7 lines
Quoted 4 lines

I guess I can see a valid reason here, but they are only helper macro's making life easier for people who do need to use these and are on par with the non-binary versions. And we already have quite some binary attributes, probably far less then normal ones :)

I only count about 100 valid binary files in the tree at the moment, that's not really all that many to handle.

100 is quite a few :) But point taken.

Quoted 5 lines
Quoted 3 lines

Anyway, wouldn't all users be reviewed anyway? But I guess it's a small safety net to make it not TOO easy.

exactly :)

I aggree and this is a v2 that strips all the additional bits.

A few comments left below.

Quoted 15 lines
Quoted 15 lines
Quoted 5 lines
Quoted 2 lines

The attached patch should help here.

Can you give me an example of using these macros? I seem to be lost in them somehow, or maybe my morning coffee just hasn't kicked in...

Yeah, I kinda added the whole shebang there :) I was trying being helpful :(

Quoted 8 lines
Quoted 6 lines

I suppose one more additional helper wouldn't be bad to have:

#define ATTRIBUTE_(BIN_)GROUPS_R[O/W](_name(, _size)) \
ATTRIBUTE_(BIN_)ATTR_R[O/W](_name, _size); \
ATTRIBUTE_(BIN_)GROUPS(_name)

Would that ever be needed?

Quoted 8 lines
Quoted 5 lines

Of ourse, by the lazy :)

I think now you create an attribute in a group as this (with this patch):

ATTRIBUTE_ATTR_RO(name, SIZE);

but "raw" attributes are rare, you really want a "device", "class", or "bus" attribute, right?

I suppose so, But I got stuck in the rare case some how initially. I registered my driver with module_platform_driver(); and in that struct i had the "device_driver" which had a group attribute so I used that. I already learned from maxime that that is the wrong way :) and hopefully I'll figure out what the right way will be soon ;)

Quoted 113 lines
Quoted 11 lines

ATTRIBUTE_GROUPS(name);

.group = name;

After that last addition, you'd simply do:
ATTRIBUTE_GROUPS_RO(name);

.group = name;

saves a whole line :)

Not worth it :)

Quoted 83 lines
Quoted 53 lines
Quoted 53 lines
Quoted 1 line

From 003ab7a74ff689daa6934e7bc50c498b2d35a1cc Mon Sep 17 00:00:00 2001

From: Oliver Schinagl <[email protected]>
Date: Thu, 11 Jul 2013 13:48:18 +0200
Subject: [PATCH] sysfs: add more helper macro's for (bin_)attribute(_groups)

With the recent changes to sysfs there's various helper macro's. However there's no RW, RO BIN_ helper macro's. This patch adds them.

Additionally there are no BIN_ group helpers so there's that aswell Moreso, if both bin and normal attribute groups are used, there's a simple helper for that, though the naming code be better. _TXT_ for the show/store ones and neither TXT or BIN for both, but that would change things to extensivly.

Finally there's also helpers for ATTRIBUTE_ATTRS.

After this patch, create default attributes can be as easy as:

ATTRIBUTE_(BIN_)ATTR_RO(name, SIZE);
ATTRIBUTE_BIN_GROUPS(name);

---
  include/linux/sysfs.h | 96 ++++++++++++++++++++++++++++++++++++++++++++-------
  1 file changed, 84 insertions(+), 12 deletions(-)
include/linux/sysfs.h +9 -3
index 2c3b6a3..0ebed11 100644
@@ -17,6 +17,7 @@
  #include <linux/list.h>
  #include <linux/lockdep.h>
  #include <linux/kobject_ns.h>
+#include <linux/stat.h>
  #include <linux/atomic.h>
 
  struct kobject;
@@ -94,15 +95,32 @@ struct attribute_group {
  #define __ATTR_IGNORE_LOCKDEP	__ATTR
  #endif
 
-#define ATTRIBUTE_GROUPS(name)					\
-static const struct attribute_group name##_group = {		\
-	.attrs = name##_attrs,					\
+#define __ATTRIBUTE_GROUPS(_name)				\
+static const struct attribute_group *_name##_groups[] = {	\
+	&_name##_group,						\
+	NULL,							\
+}
+
+#define ATTRIBUTE_GROUPS(_name)					\
+static const struct attribute_group _name##_group = {		\
Quoted 8 lines

include/linux/sysfs.h struct attribute_group { · line 111

Quoted 8 lines
include/linux/sysfs.h +5 -2
+	.attrs = _name##_attrs,					\
  };								\
-static const struct attribute_group *name##_groups[] = {	\
-	&name##_group,						\
+__ATTRIBUTE_GROUPS(_name)
+
+#define __ATTRIBUTE_ATTRS(_name)				\
+struct bin_attribute *_name##_attrs[] = {			\

typo here, scrap bin_ copy paste fail!

Quoted 4 lines
Quoted 4 lines
include/linux/sysfs.h +1 -0
+	&_name##_attr,						\
  	NULL,							\
  }
 
Quoted 10 lines

include/linux/sysfs.h struct attribute_group { · line 122

Quoted 7 lines
include/linux/sysfs.h +7 -0
+#define ATTRIBUTE_ATTR_RO(_name, _size)				\
+struct attribute _name##_attr = __ATTR_RO(_name, _size);	\
+__ATTRIBUTE_ATTRS(_name)
+
+#define ATTRIBUTE_ATTR_RW(_name, _size)				\
+struct attribute _name##_attr = __ATTR_RW(_name, _size);	\
+__ATTRIBUTE_ATTRS(_name)

What do these two help out with? "attribute attribute read-write" seems a bit "clunky", don't you think? :)

I aggree, but I tried to stick with the ATTRIBUTE_GROUP naming and that's the best I could come up with.

Unless I completely misunderstood (which isn't all that unlikely) the following is needed to create a group using a .group.

Quoted 8 lines

So you pass group an array of attribute_group pointers. The ATTRIBUTE_GROUPS helps there, right? It saves the typing of creating the array of groups and adding groups to that.

So a group consists of an array of attributes if I understood right and that array needs to be filled with pointers attributes? well those ATTRIBUTE_ATTR's do just that. Granted, maybe the naming is poor, but just ATTRS() felt to short.

Here's an example of a file I converted to use the ATTRIBUTE_GROUP() macro attached below (net/wireless/sysfs). As is, it's an increase of only 2 lines to the file overall, which is about normal for the conversion. As you can see, you still need a list of attributes (which someone has already said I need another macro for, to stop typing "&dev_attr*.attr" all the time).

Quoted 2 lines

With your macros, how would a file be converted to use them? Perhaps that will help explain things to me better.

Heh, they can't I don't think.

Quoted 49 lines
Quoted 9 lines
Quoted 7 lines

include/linux/sysfs.h struct attribute_group {

Quoted 7 lines
include/linux/sysfs.h +5 -0
+#define ATTRIBUTE_BIN_GROUPS(_name)					\
+static const struct attribute_group _name##_bin_group = {		\
+	.bin_attrs = _name##_bin_attrs,					\
+};									\
+__ATTRIBUTE_BIN_GROUPS(_name)

This is the equiv. of ATTRIBUTE_GROUPS(_name) which creates an attribute group, with only a binary attribute instead.

Again, binary files are rare, and should be rare, don't make it too easy to create them :)

Quoted 36 lines
Quoted 3 lines

include/linux/sysfs.h

Quoted 3 lines
include/linux/sysfs.h +3 -0
+#define ATTRIBUTE_BIN_ATTR_RW(_name, _size)				\
+struct bin_attribute _name##_bin_attr = __BIN_ATTR_RW(_name, _size);	\
+__ATTRIBUTE_BIN_ATTRS(_name)

These I guess are the equivialent what ATTRIBUTE_GROUP is for groups, but now for the attributes that go in groups?

Quoted 2 lines

Can you show me how these would be used in a real-world example?

Well my real world is currently limited by my own driver. If I may copy paste from there:

ATTRIBUTE_BIN_ATTR_RO(sunxi_sid, SID_SIZE);
ATTRIBUTE_BIN_GROUPS(sunxi_sid);

static struct platform_driver sunxi_sid_driver = {
.probe = sunxi_sid_probe,
.remove = sunxi_sid_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE, .of_match_table = sunxi_sid_of_match, .groups = sunxi_sid_bin_groups,
},
};
module_platform_driver(sunxi_sid_driver);

But if you say, you want to be a little less complete, we can drop ATTRIBUTE_BIN_ATTR_R[OW]() forcing you to do this instead:

struct bin_attribute sunxi_sid_bin_attr = __BIN_ATTR_RO(eeprom, SID_SIZE);

struct bin_attribute *sunxi_sid_bin_attrs[] = {
&sunxi_sid_bin_attr,
NULL,
};

Quoted 6 lines
Quoted 3 lines

Which requires some manual labor yet still has the __BIN_ATTR_R[OW] macro's to help with some of the more tedious work and allowing you to name the binary attributes nicer?

BIN_ATTR_RO() is fine, I'd stick with that for now, it's getting confusing enough as-is :)

Agreed and attached.

Quoted 7 lines

thanks,

greg k-h

From 669597be47d042ee28abe5f7e172054043b003e7 Mon Sep 17 00:00:00 2001

From: Oliver Schinagl <[email protected]>
Date: Thu, 11 Jul 2013 13:48:18 +0200
Subject: [PATCH 1/2] sysfs: add more helper macro's for
(bin_)attribute(_groups)

With the recent changes to sysfs there's various helper macro's. However there's no RW, RO BIN_ helper macro's. This patch adds them.

---
 include/linux/sysfs.h | 51 ++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 38 insertions(+), 13 deletions(-)
include/linux/sysfs.h +38 -13
index 2c3b6a3..5cf502f 100644
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/lockdep.h>
 #include <linux/kobject_ns.h>
+#include <linux/stat.h>
 #include <linux/atomic.h>
 
 struct kobject;
@@ -94,15 +95,18 @@ struct attribute_group {
 #define __ATTR_IGNORE_LOCKDEP	__ATTR
 #endif
 
-#define ATTRIBUTE_GROUPS(name)					\
-static const struct attribute_group name##_group = {		\
-	.attrs = name##_attrs,					\
-};								\
-static const struct attribute_group *name##_groups[] = {	\
-	&name##_group,						\
+#define __ATTRIBUTE_GROUPS(_name)				\
+static const struct attribute_group *_name##_groups[] = {	\
+	&_name##_group,						\
 	NULL,							\
 }
 
+#define ATTRIBUTE_GROUPS(_name)					\
+static const struct attribute_group _name##_group = {		\
+	.attrs = _name##_attrs,					\
+};								\
+__ATTRIBUTE_GROUPS(_name)
+
 #define attr_name(_attr) (_attr).attr.name
 
 struct file;
@@ -132,15 +136,36 @@ struct bin_attribute {
  */
 #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
 
-/* macro to create static binary attributes easier */
-#define BIN_ATTR(_name, _mode, _read, _write, _size)		\
-struct bin_attribute bin_attr_##_name = {			\
-	.attr = {.name = __stringify(_name), .mode = _mode },	\
-	.read	= _read,					\
-	.write	= _write,					\
-	.size	= _size,					\
+/* macros to create static binary attributes easier */
+#define __BIN_ATTR(_name, _mode, _read, _write, _size) {		\
+	.attr = { .name = __stringify(_name), .mode = _mode },		\
+	.read	= _read,						\
+	.write	= _write,						\
+	.size	= _size,						\
+}
+
+#define __BIN_ATTR_RO(_name, _size) {					\
+	.attr	= { .name = __stringify(_name), .mode = S_IRUGO },	\
+	.read	= _name##_read,						\
+	.size	= _size,						\
 }
 
+#define __BIN_ATTR_RW(_name, _size) __BIN_ATTR(_name,			\
+				   (S_IWUSR | S_IRUGO), _name##_read,	\
+				   _name##_write)
+
+#define __BIN_ATTR_NULL __ATTR_NULL
+
+#define BIN_ATTR(_name, _mode, _read, _write, _size)			\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR(_name, _mode, _read,	\
+					_write, _size)
+
+#define BIN_RO_ATTR(_name, _size)					\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR_RO(_name, _size)
+
+#define BIN_RW_ATTR(_name, _size)					\
+struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size)
+
 struct sysfs_ops {
 	ssize_t	(*show)(struct kobject *, struct attribute *,char *);
 	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
Signature · 1 line
1.8.1.5
#23 lore raw

Re: [PATCH v2 2/7] sysfs.h: add ATTRIBUTE_GROUPS() macro

Greg,

Haven't heard anything about this v2 patch, I know you are very busy but with the merge window closing today/yesterday just wondering about the status of it all.

Oliver

Quoted 239 lines · Oliver Schinagl
Quoted 13 lines · Greg Kroah-Hartman
Quoted 12 lines · Oliver Schinagl
Quoted 11 lines · Greg Kroah-Hartman
Quoted 5 lines · Oliver Schinagl
Quoted 3 lines · Greg Kroah-Hartman

To make it easier for driver subsystems to work with attribute groups, create the ATTRIBUTE_GROUPS macro to remove some of the repetitive typing for the most common use for attribute groups.

But binary groups are discriminated against :(

Yes, as they are "rarer" by far, as they should be. binary sysfs files should almost never be used, as they are only "pass-through" files to the hardware, so I want to see you do more work in order to use them, as they should not be created lightly.

Quoted 7 lines
Quoted 4 lines

I guess I can see a valid reason here, but they are only helper macro's making life easier for people who do need to use these and are on par with the non-binary versions. And we already have quite some binary attributes, probably far less then normal ones :)

I only count about 100 valid binary files in the tree at the moment, that's not really all that many to handle.

100 is quite a few :) But point taken.

Quoted 5 lines
Quoted 3 lines

Anyway, wouldn't all users be reviewed anyway? But I guess it's a small safety net to make it not TOO easy.

exactly :)

I aggree and this is a v2 that strips all the additional bits.

A few comments left below.

Quoted 15 lines
Quoted 15 lines
Quoted 5 lines
Quoted 2 lines

The attached patch should help here.

Can you give me an example of using these macros? I seem to be lost in them somehow, or maybe my morning coffee just hasn't kicked in...

Yeah, I kinda added the whole shebang there :) I was trying being helpful :(

Quoted 8 lines
Quoted 6 lines

I suppose one more additional helper wouldn't be bad to have:

#define ATTRIBUTE_(BIN_)GROUPS_R[O/W](_name(, _size)) \
ATTRIBUTE_(BIN_)ATTR_R[O/W](_name, _size); \
ATTRIBUTE_(BIN_)GROUPS(_name)

Would that ever be needed?

Quoted 8 lines
Quoted 5 lines

Of ourse, by the lazy :)

I think now you create an attribute in a group as this (with this patch):

ATTRIBUTE_ATTR_RO(name, SIZE);

but "raw" attributes are rare, you really want a "device", "class", or "bus" attribute, right?

I suppose so, But I got stuck in the rare case some how initially. I registered my driver with module_platform_driver(); and in that struct i had the "device_driver" which had a group attribute so I used that. I already learned from maxime that that is the wrong way :) and hopefully I'll figure out what the right way will be soon ;)

Quoted 115 lines
Quoted 11 lines

ATTRIBUTE_GROUPS(name);

.group = name;

After that last addition, you'd simply do:
ATTRIBUTE_GROUPS_RO(name);

.group = name;

saves a whole line :)

Not worth it :)

Quoted 85 lines
Quoted 55 lines
Quoted 55 lines
Quoted 1 line

From 003ab7a74ff689daa6934e7bc50c498b2d35a1cc Mon Sep 17 00:00:00

2001
From: Oliver Schinagl <[email protected]>
Date: Thu, 11 Jul 2013 13:48:18 +0200
Subject: [PATCH] sysfs: add more helper macro's for (bin_)attribute(_groups)

With the recent changes to sysfs there's various helper macro's. However there's no RW, RO BIN_ helper macro's. This patch adds them.

Additionally there are no BIN_ group helpers so there's that aswell Moreso, if both bin and normal attribute groups are used, there's a simple helper for that, though the naming code be better. _TXT_ for the show/store ones and neither TXT or BIN for both, but that would change things to extensivly.

Finally there's also helpers for ATTRIBUTE_ATTRS.

After this patch, create default attributes can be as easy as:

ATTRIBUTE_(BIN_)ATTR_RO(name, SIZE);
ATTRIBUTE_BIN_GROUPS(name);

---
  include/linux/sysfs.h | 96 
++++++++++++++++++++++++++++++++++++++++++++-------
  1 file changed, 84 insertions(+), 12 deletions(-)
include/linux/sysfs.h +9 -3
index 2c3b6a3..0ebed11 100644
@@ -17,6 +17,7 @@
  #include <linux/list.h>
  #include <linux/lockdep.h>
  #include <linux/kobject_ns.h>
+#include <linux/stat.h>
  #include <linux/atomic.h>
 
  struct kobject;
@@ -94,15 +95,32 @@ struct attribute_group {
  #define __ATTR_IGNORE_LOCKDEP    __ATTR
  #endif
 
-#define ATTRIBUTE_GROUPS(name)                    \
-static const struct attribute_group name##_group = {        \
-    .attrs = name##_attrs,                    \
+#define __ATTRIBUTE_GROUPS(_name)                \
+static const struct attribute_group *_name##_groups[] = {    \
+    &_name##_group,                        \
+    NULL,                            \
+}
+
+#define ATTRIBUTE_GROUPS(_name)                    \
+static const struct attribute_group _name##_group = {        \
Quoted 8 lines

include/linux/sysfs.h struct attribute_group {

Quoted 8 lines
include/linux/sysfs.h +5 -2
+    .attrs = _name##_attrs,                    \
  };                                \
-static const struct attribute_group *name##_groups[] = {    \
-    &name##_group,                        \
+__ATTRIBUTE_GROUPS(_name)
+
+#define __ATTRIBUTE_ATTRS(_name)                \
+struct bin_attribute *_name##_attrs[] = {            \

typo here, scrap bin_ copy paste fail!

Quoted 4 lines
Quoted 4 lines
include/linux/sysfs.h +1 -0
+ &_name##_attr,                        \
      NULL,                            \
  }
 
Quoted 10 lines

include/linux/sysfs.h struct attribute_group { · line 122

Quoted 7 lines
include/linux/sysfs.h +7 -0
+#define ATTRIBUTE_ATTR_RO(_name, _size)                \
+struct attribute _name##_attr = __ATTR_RO(_name, _size);    \
+__ATTRIBUTE_ATTRS(_name)
+
+#define ATTRIBUTE_ATTR_RW(_name, _size)                \
+struct attribute _name##_attr = __ATTR_RW(_name, _size);    \
+__ATTRIBUTE_ATTRS(_name)

What do these two help out with? "attribute attribute read-write" seems a bit "clunky", don't you think? :)

I aggree, but I tried to stick with the ATTRIBUTE_GROUP naming and that's the best I could come up with.

Unless I completely misunderstood (which isn't all that unlikely) the following is needed to create a group using a .group.

Quoted 8 lines

So you pass group an array of attribute_group pointers. The ATTRIBUTE_GROUPS helps there, right? It saves the typing of creating the array of groups and adding groups to that.

So a group consists of an array of attributes if I understood right and that array needs to be filled with pointers attributes? well those ATTRIBUTE_ATTR's do just that. Granted, maybe the naming is poor, but just ATTRS() felt to short.

Here's an example of a file I converted to use the ATTRIBUTE_GROUP() macro attached below (net/wireless/sysfs). As is, it's an increase of only 2 lines to the file overall, which is about normal for the conversion. As you can see, you still need a list of attributes (which someone has already said I need another macro for, to stop typing "&dev_attr*.attr" all the time).

Quoted 2 lines

With your macros, how would a file be converted to use them? Perhaps that will help explain things to me better.

Heh, they can't I don't think.

Quoted 50 lines
Quoted 9 lines
Quoted 7 lines

include/linux/sysfs.h struct attribute_group {

Quoted 7 lines
include/linux/sysfs.h +5 -0
+#define ATTRIBUTE_BIN_GROUPS(_name)                    \
+static const struct attribute_group _name##_bin_group = {        \
+    .bin_attrs = _name##_bin_attrs,                    \
+};                                    \
+__ATTRIBUTE_BIN_GROUPS(_name)

This is the equiv. of ATTRIBUTE_GROUPS(_name) which creates an attribute group, with only a binary attribute instead.

Again, binary files are rare, and should be rare, don't make it too easy to create them :)

Quoted 37 lines
Quoted 4 lines
Quoted 4 lines
include/linux/sysfs.h +2 -0
+#define ATTRIBUTE_BIN_ATTR_RW(_name, _size)                \
+struct bin_attribute _name##_bin_attr = __BIN_ATTR_RW(_name, 

_size); \
+__ATTRIBUTE_BIN_ATTRS(_name)

These I guess are the equivialent what ATTRIBUTE_GROUP is for groups, but now for the attributes that go in groups?

Quoted 2 lines

Can you show me how these would be used in a real-world example?

Well my real world is currently limited by my own driver. If I may copy paste from there:

ATTRIBUTE_BIN_ATTR_RO(sunxi_sid, SID_SIZE);
ATTRIBUTE_BIN_GROUPS(sunxi_sid);

static struct platform_driver sunxi_sid_driver = {
.probe = sunxi_sid_probe,
.remove = sunxi_sid_remove,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE, .of_match_table = sunxi_sid_of_match, .groups = sunxi_sid_bin_groups,
},
}; module_platform_driver(sunxi_sid_driver);

But if you say, you want to be a little less complete, we can drop ATTRIBUTE_BIN_ATTR_R[OW]() forcing you to do this instead:

struct bin_attribute sunxi_sid_bin_attr = __BIN_ATTR_RO(eeprom, SID_SIZE);

struct bin_attribute *sunxi_sid_bin_attrs[] = {
&sunxi_sid_bin_attr,
NULL,
};

Quoted 6 lines
Quoted 3 lines

Which requires some manual labor yet still has the __BIN_ATTR_R[OW] macro's to help with some of the more tedious work and allowing you to name the binary attributes nicer?

BIN_ATTR_RO() is fine, I'd stick with that for now, it's getting confusing enough as-is :)

Agreed and attached.

Quoted 5 lines

thanks,

greg k-h

author maintainer
#24 lore raw

Re: [PATCH v2 2/7] sysfs.h: add ATTRIBUTE_GROUPS() macro

Quoted 5 lines · Oliver Schinagl

Greg,

Haven't heard anything about this v2 patch, I know you are very busy but with the merge window closing today/yesterday just wondering about the status of it all.

Just refreshed them against 3.11-rc1 and sent them out a mere seconds ago :)

thanks,

greg k-h

#25 lore raw

Re: [PATCH v2 2/7] sysfs.h: add ATTRIBUTE_GROUPS() macro

In reply to Greg Kroah-Hartman
Quoted 3 lines · Greg Kroah-Hartman

To make it easier for driver subsystems to work with attribute groups, create the ATTRIBUTE_GROUPS macro to remove some of the repetitive typing for the most common use for attribute groups.

Forgot to add this trivial little cleanup patch with my previous mail, I know you don't like patch dependancies, but this one depends on the previous one as that included stat.h, if you decide my previous patch isn't good, i can redo this one with stat.h included (and move atomic.h to the top to keep includes alphabetically ordered).

Oliver

Quoted 28 lines
---
  include/linux/sysfs.h | 9 +++++++++
  1 file changed, 9 insertions(+)
include/linux/sysfs.h +9 -0
index 9cd20c8..f62ff01 100644
@@ -94,6 +94,15 @@ struct attribute_group {
  #define __ATTR_IGNORE_LOCKDEP	__ATTR
  #endif
 
+#define ATTRIBUTE_GROUPS(name)					\
+static const struct attribute_group name##_group = {		\
+	.attrs = name##_attrs,					\
+};								\
+static const struct attribute_group *name##_groups[] = {	\
+	&name##_group,						\
+	NULL,							\
+}
+
  #define attr_name(_attr) (_attr).attr.name
 
  struct file;
Quoted 1 line

From a67de9f026363ce821c72a807d98830abece3cf7 Mon Sep 17 00:00:00 2001

From: Oliver Schinagl <[email protected]>
Date: Thu, 11 Jul 2013 13:57:42 +0200
Subject: [PATCH] sysfs: use file mode defines from stat.h

With the last patches stat.h was included to the header, and thus those permission defines should be used.

---
 include/linux/sysfs.h | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)
include/linux/sysfs.h +9 -8
index 0ebed11..8f820c7 100644
@@ -69,18 +69,19 @@ struct attribute_group {
  * for examples..
  */
 
-#define __ATTR(_name,_mode,_show,_store) { \
-	.attr = {.name = __stringify(_name), .mode = _mode },	\
-	.show	= _show,					\
-	.store	= _store,					\
+#define __ATTR(_name,_mode,_show,_store) { 				\
+	.attr = {.name = __stringify(_name), .mode = _mode },		\
+	.show	= _show,						\
+	.store	= _store,						\
 }
 
-#define __ATTR_RO(_name) { \
-	.attr	= { .name = __stringify(_name), .mode = 0444 },	\
-	.show	= _name##_show,					\
+#define __ATTR_RO(_name) {						\
+	.attr	= { .name = __stringify(_name), .mode = S_IRUGO },	\
+	.show	= _name##_show,						\
 }
 
-#define __ATTR_RW(_name) __ATTR(_name, 0644, _name##_show, _name##_store)
+#define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO),		\
+			 _name##_show, _name##_store)
 
 #define __ATTR_NULL { .attr = { .name = NULL } }
 
Signature · 1 line
1.8.1.5
author maintainer
#26 lore raw

Re: [PATCH v2 2/7] sysfs.h: add ATTRIBUTE_GROUPS() macro

Quoted 10 lines · Oliver Schinagl
Quoted 3 lines · Greg Kroah-Hartman

To make it easier for driver subsystems to work with attribute groups, create the ATTRIBUTE_GROUPS macro to remove some of the repetitive typing for the most common use for attribute groups.

Forgot to add this trivial little cleanup patch with my previous mail, I know you don't like patch dependancies, but this one depends on the previous one as that included stat.h, if you decide my previous patch isn't good, i can redo this one with stat.h included (and move atomic.h to the top to keep includes alphabetically ordered).

No problem, I can merge this with your other one when I can figure out what that one is really doing :)

thanks,

greg k-h

author maintainer
#27 lore raw

PATCH v2 3/7 sysfs.h: add BIN_ATTR macro

In reply to Greg Kroah-Hartman

This makes it easier to create static binary attributes, which is needed in a number of drivers, instead of "open coding" them.

---
 include/linux/sysfs.h | 9 +++++++++
 1 file changed, 9 insertions(+)
include/linux/sysfs.h +9 -0
index f62ff01..d50a96b 100644
@@ -132,6 +132,15 @@ struct bin_attribute {
  */
 #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
 
+/* macro to create static binary attributes easier */
+#define BIN_ATTR(_name, _mode, _read, _write, _size)		\
+struct bin_attribute bin_attr_##_name = {			\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.read	= _read,					\
+	.write	= _write,					\
+	.size	= _size,					\
+}
+
 struct sysfs_ops {
 	ssize_t	(*show)(struct kobject *, struct attribute *,char *);
 	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
author maintainer
#28 lore raw

PATCH v2 4/7 driver core: device.h: add RW and RO attribute macros

In reply to Greg Kroah-Hartman

Make it easier to create attributes without having to always audit the mode settings.

---
 include/linux/device.h | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)
include/linux/device.h +21 -7
index bcf8c0d..f207a8f 100644
@@ -47,7 +47,11 @@ struct bus_attribute {
 };
 
 #define BUS_ATTR(_name, _mode, _show, _store)	\
-struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
+	struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
+#define BUS_ATTR_RW(_name) \
+	struct bus_attribute bus_attr_##_name = __ATTR_RW(_name)
+#define BUS_ATTR_RO(_name) \
+	struct bus_attribute bus_attr_##_name = __ATTR_RO(_name)
 
 extern int __must_check bus_create_file(struct bus_type *,
 					struct bus_attribute *);
@@ -261,9 +265,12 @@ struct driver_attribute {
 			 size_t count);
 };
 
-#define DRIVER_ATTR(_name, _mode, _show, _store)	\
-struct driver_attribute driver_attr_##_name =		\
-	__ATTR(_name, _mode, _show, _store)
+#define DRIVER_ATTR(_name, _mode, _show, _store) \
+	struct driver_attribute driver_attr_##_name = __ATTR(_name, _mode, _show, _store)
+#define DRIVER_ATTR_RW(_name) \
+	struct driver_attribute driver_attr_##_name = __ATTR_RW(_name)
+#define DRIVER_ATTR_RO(_name) \
+	struct driver_attribute driver_attr_##_name = __ATTR_RO(_name)
 
 extern int __must_check driver_create_file(struct device_driver *driver,
 					const struct driver_attribute *attr);
@@ -414,8 +421,12 @@ struct class_attribute {
 				 const struct class_attribute *attr);
 };
 
-#define CLASS_ATTR(_name, _mode, _show, _store)			\
-struct class_attribute class_attr_##_name = __ATTR(_name, _mode, _show, _store)
+#define CLASS_ATTR(_name, _mode, _show, _store) \
+	struct class_attribute class_attr_##_name = __ATTR(_name, _mode, _show, _store)
+#define CLASS_ATTR_RW(_name) \
+	struct class_attribute class_attr_##_name = __ATTR_RW(_name)
+#define CLASS_ATTR_RO(_name) \
+	struct class_attribute class_attr_##_name = __ATTR_RO(_name)
 
 extern int __must_check class_create_file(struct class *class,
 					  const struct class_attribute *attr);
@@ -423,7 +434,6 @@ extern void class_remove_file(struct class *class,
 			      const struct class_attribute *attr);
 
 /* Simple class attribute that is just a static string */
-
 struct class_attribute_string {
 	struct class_attribute attr;
 	char *str;
@@ -512,6 +522,10 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
 
 #define DEVICE_ATTR(_name, _mode, _show, _store) \
 	struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
+#define DEVICE_ATTR_RW(_name) \
+	struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
+#define DEVICE_ATTR_RO(_name) \
+	struct device_attribute dev_attr_##_name = __ATTR_RO(_name)
 #define DEVICE_ULONG_ATTR(_name, _mode, _var) \
 	struct dev_ext_attribute dev_attr_##_name = \
 		{ __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
author maintainer
#29 lore raw

PATCH v2 5/7 sysfs: add support for binary attributes in groups

In reply to Greg Kroah-Hartman

groups should be able to support binary attributes, just like it supports "normal" attributes. This lets us only handle one type of structure, groups, throughout the driver core and subsystems, making binary attributes a "full fledged" part of the driver model, and not something just "tacked on".

---
 fs/sysfs/group.c      | 66 +++++++++++++++++++++++++++++++++++----------------
 include/linux/sysfs.h |  4 ++--
 2 files changed, 48 insertions(+), 22 deletions(-)
fs/sysfs/group.c +46 -20
index aec3d5c..e5719c6 100644
@@ -20,38 +20,64 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
 			 const struct attribute_group *grp)
 {
 	struct attribute *const* attr;
-	int i;
+	struct bin_attribute *const* bin_attr;
 
-	for (i = 0, attr = grp->attrs; *attr; i++, attr++)
-		sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
+	if (grp->attrs)
+		for (attr = grp->attrs; *attr; attr++)
+			sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
+	if (grp->bin_attrs)
+		for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
+			sysfs_remove_bin_file(kobj, *bin_attr);
 }
 
 static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
 			const struct attribute_group *grp, int update)
 {
 	struct attribute *const* attr;
+	struct bin_attribute *const* bin_attr;
 	int error = 0, i;
 
-	for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
-		umode_t mode = 0;
+	if (grp->attrs) {
+		for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
+			umode_t mode = 0;
+
+			/*
+			 * In update mode, we're changing the permissions or
+			 * visibility.  Do this by first removing then
+			 * re-adding (if required) the file.
+			 */
+			if (update)
+				sysfs_hash_and_remove(dir_sd, NULL,
+						      (*attr)->name);
+			if (grp->is_visible) {
+				mode = grp->is_visible(kobj, *attr, i);
+				if (!mode)
+					continue;
+			}
+			error = sysfs_add_file_mode(dir_sd, *attr,
+						    SYSFS_KOBJ_ATTR,
+						    (*attr)->mode | mode);
+			if (unlikely(error))
+				break;
+		}
+		if (error) {
+			remove_files(dir_sd, kobj, grp);
+			goto exit;
+		}
+	}
 
-		/* in update mode, we're changing the permissions or
-		 * visibility.  Do this by first removing then
-		 * re-adding (if required) the file */
-		if (update)
-			sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
-		if (grp->is_visible) {
-			mode = grp->is_visible(kobj, *attr, i);
-			if (!mode)
-				continue;
+	if (grp->bin_attrs) {
+		for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
+			if (update)
+				sysfs_remove_bin_file(kobj, *bin_attr);
+			error = sysfs_create_bin_file(kobj, *bin_attr);
+			if (error)
+				break;
 		}
-		error = sysfs_add_file_mode(dir_sd, *attr, SYSFS_KOBJ_ATTR,
-					    (*attr)->mode | mode);
-		if (unlikely(error))
-			break;
+		if (error)
+			remove_files(dir_sd, kobj, grp);
 	}
-	if (error)
-		remove_files(dir_sd, kobj, grp);
+exit:
 	return error;
 }
 
include/linux/sysfs.h +2 -2
index d50a96b..2c3b6a3 100644
@@ -21,6 +21,7 @@
 
 struct kobject;
 struct module;
+struct bin_attribute;
 enum kobj_ns_type;
 
 struct attribute {
@@ -59,10 +60,9 @@ struct attribute_group {
 	umode_t			(*is_visible)(struct kobject *,
 					      struct attribute *, int);
 	struct attribute	**attrs;
+	struct bin_attribute	**bin_attrs;
 };
 
-
-
 /**
  * Use these macros to make defining attributes easier. See include/linux/device.h
  * for examples..
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
#30 lore raw

Re: [PATCH v2 5/7] sysfs: add support for binary attributes in groups

Quoted 5 lines · Greg Kroah-Hartman

groups should be able to support binary attributes, just like it supports "normal" attributes. This lets us only handle one type of structure, groups, throughout the driver core and subsystems, making binary attributes a "full fledged" part of the driver model, and not something just "tacked on".

However when only using binary attributes it warns and doesn't create anything. The attached patch fixes that.

Quoted 2 lines

If I may be so bold and ask to change my e-mail address to <[email protected]> that would be kind. I use the +list delimiter to put all the mailing list mails in a separate mailbox.

Quoted 121 lines
---
  fs/sysfs/group.c      | 66 +++++++++++++++++++++++++++++++++++----------------
  include/linux/sysfs.h |  4 ++--
  2 files changed, 48 insertions(+), 22 deletions(-)
fs/sysfs/group.c +46 -20
index aec3d5c..e5719c6 100644
@@ -20,38 +20,64 @@ static void remove_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
  			 const struct attribute_group *grp)
  {
  	struct attribute *const* attr;
-	int i;
+	struct bin_attribute *const* bin_attr;
 
-	for (i = 0, attr = grp->attrs; *attr; i++, attr++)
-		sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
+	if (grp->attrs)
+		for (attr = grp->attrs; *attr; attr++)
+			sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
+	if (grp->bin_attrs)
+		for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
+			sysfs_remove_bin_file(kobj, *bin_attr);
  }
 
  static int create_files(struct sysfs_dirent *dir_sd, struct kobject *kobj,
  			const struct attribute_group *grp, int update)
  {
  	struct attribute *const* attr;
+	struct bin_attribute *const* bin_attr;
  	int error = 0, i;
 
-	for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
-		umode_t mode = 0;
+	if (grp->attrs) {
+		for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
+			umode_t mode = 0;
+
+			/*
+			 * In update mode, we're changing the permissions or
+			 * visibility.  Do this by first removing then
+			 * re-adding (if required) the file.
+			 */
+			if (update)
+				sysfs_hash_and_remove(dir_sd, NULL,
+						      (*attr)->name);
+			if (grp->is_visible) {
+				mode = grp->is_visible(kobj, *attr, i);
+				if (!mode)
+					continue;
+			}
+			error = sysfs_add_file_mode(dir_sd, *attr,
+						    SYSFS_KOBJ_ATTR,
+						    (*attr)->mode | mode);
+			if (unlikely(error))
+				break;
+		}
+		if (error) {
+			remove_files(dir_sd, kobj, grp);
+			goto exit;
+		}
+	}
 
-		/* in update mode, we're changing the permissions or
-		 * visibility.  Do this by first removing then
-		 * re-adding (if required) the file */
-		if (update)
-			sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
-		if (grp->is_visible) {
-			mode = grp->is_visible(kobj, *attr, i);
-			if (!mode)
-				continue;
+	if (grp->bin_attrs) {
+		for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
+			if (update)
+				sysfs_remove_bin_file(kobj, *bin_attr);
+			error = sysfs_create_bin_file(kobj, *bin_attr);
+			if (error)
+				break;
  		}
-		error = sysfs_add_file_mode(dir_sd, *attr, SYSFS_KOBJ_ATTR,
-					    (*attr)->mode | mode);
-		if (unlikely(error))
-			break;
+		if (error)
+			remove_files(dir_sd, kobj, grp);
  	}
-	if (error)
-		remove_files(dir_sd, kobj, grp);
+exit:
  	return error;
  }
 
include/linux/sysfs.h +2 -2
index d50a96b..2c3b6a3 100644
@@ -21,6 +21,7 @@
 
  struct kobject;
  struct module;
+struct bin_attribute;
  enum kobj_ns_type;
 
  struct attribute {
@@ -59,10 +60,9 @@ struct attribute_group {
  	umode_t			(*is_visible)(struct kobject *,
  					      struct attribute *, int);
  	struct attribute	**attrs;
+	struct bin_attribute	**bin_attrs;
  };
 
-
-
  /**
   * Use these macros to make defining attributes easier. See include/linux/device.h
   * for examples..
Quoted 1 line

From 5a4066011878134c1ab9412bc147c28c30f0fa4b Mon Sep 17 00:00:00 2001

From: Oliver Schinagl <[email protected]>
Date: Thu, 11 Jul 2013 13:40:20 +0200
Subject: [PATCH] sysfs: prevent warning when only using binary attributes

When only using bin_attrs instead of attrs the kernel prints a warning and refuses to create the sysfs entry. This fixes that.

---
 fs/sysfs/group.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/sysfs/group.c +2 -2
index e5719c6..09a1a25 100644
@@ -93,8 +93,8 @@ static int internal_create_group(struct kobject *kobj, int update,
 	/* Updates may happen before the object has been instantiated */
 	if (unlikely(update && !kobj->sd))
 		return -EINVAL;
-	if (!grp->attrs) {
-		WARN(1, "sysfs: attrs not set by subsystem for group: %s/%s\n",
+	if (!grp->attrs && !grp->bin_attrs) {
+		WARN(1, "sysfs: (bin_)attrs not set by subsystem for group: %s/%s\n",
 			kobj->name, grp->name ? "" : grp->name);
 		return -EINVAL;
 	}
Signature · 1 line
1.8.1.5
author maintainer
#31 lore raw

Re: [PATCH v2 5/7] sysfs: add support for binary attributes in groups

Quoted 8 lines · Oliver Schinagl
Quoted 5 lines · Greg Kroah-Hartman

groups should be able to support binary attributes, just like it supports "normal" attributes. This lets us only handle one type of structure, groups, throughout the driver core and subsystems, making binary attributes a "full fledged" part of the driver model, and not something just "tacked on".

However when only using binary attributes it warns and doesn't create anything. The attached patch fixes that.

Ah, missed that, I didn't have a binary-only attribute group to test that out, thanks.

Quoted 4 lines
Quoted 1 line

If I may be so bold and ask to change my e-mail address to <[email protected]> that would be kind. I use the +list delimiter to put all the mailing list mails in a separate mailbox.

Sure, no problem at all, will do so. And I'll queue up your attached patch as well, it looks great.

greg k-h

author maintainer
#32 lore raw

PATCH v2 6/7 driver core: Introduce device_create_groups

In reply to Greg Kroah-Hartman

From: Guenter Roeck <[email protected]>

device_create_groups lets callers create devices as well as associated sysfs attributes with a single call. This avoids race conditions seen if sysfs attributes on new devices are created later.

[fixed up comment block placement and add checks for printk buffer formats - gregkh]

---
 drivers/base/core.c    | 111 ++++++++++++++++++++++++++++++++++++-------------
 include/linux/device.h |   5 +++
 2 files changed, 88 insertions(+), 28 deletions(-)
drivers/base/core.c +83 -28
index dc3ea23..a8aae18 100644
@@ -1667,34 +1667,11 @@ static void device_create_release(struct device *dev)
 	kfree(dev);
 }
 
-/**
- * device_create_vargs - creates a device and registers it with sysfs
- * @class: pointer to the struct class that this device should be registered to
- * @parent: pointer to the parent struct device of this new device, if any
- * @devt: the dev_t for the char device to be added
- * @drvdata: the data to be added to the device for callbacks
- * @fmt: string for the device's name
- * @args: va_list for the device's name
- *
- * This function can be used by char device classes.  A struct device
- * will be created in sysfs, registered to the specified class.
- *
- * A "dev" file will be created, showing the dev_t for the device, if
- * the dev_t is not 0,0.
- * If a pointer to a parent struct device is passed in, the newly created
- * struct device will be a child of that device in sysfs.
- * The pointer to the struct device will be returned from the call.
- * Any further sysfs files that might be required can be created using this
- * pointer.
- *
- * Returns &struct device pointer on success, or ERR_PTR() on error.
- *
- * Note: the struct class passed to this function must have previously
- * been created with a call to class_create().
- */
-struct device *device_create_vargs(struct class *class, struct device *parent,
-				   dev_t devt, void *drvdata, const char *fmt,
-				   va_list args)
+static struct device *
+device_create_groups_vargs(struct class *class, struct device *parent,
+			   dev_t devt, void *drvdata,
+			   const struct attribute_group **groups,
+			   const char *fmt, va_list args)
 {
 	struct device *dev = NULL;
 	int retval = -ENODEV;
@@ -1711,6 +1688,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
 	dev->devt = devt;
 	dev->class = class;
 	dev->parent = parent;
+	dev->groups = groups;
 	dev->release = device_create_release;
 	dev_set_drvdata(dev, drvdata);
 
@@ -1728,6 +1706,39 @@ error:
 	put_device(dev);
 	return ERR_PTR(retval);
 }
+
+/**
+ * device_create_vargs - creates a device and registers it with sysfs
+ * @class: pointer to the struct class that this device should be registered to
+ * @parent: pointer to the parent struct device of this new device, if any
+ * @devt: the dev_t for the char device to be added
+ * @drvdata: the data to be added to the device for callbacks
+ * @fmt: string for the device's name
+ * @args: va_list for the device's name
+ *
+ * This function can be used by char device classes.  A struct device
+ * will be created in sysfs, registered to the specified class.
+ *
+ * A "dev" file will be created, showing the dev_t for the device, if
+ * the dev_t is not 0,0.
+ * If a pointer to a parent struct device is passed in, the newly created
+ * struct device will be a child of that device in sysfs.
+ * The pointer to the struct device will be returned from the call.
+ * Any further sysfs files that might be required can be created using this
+ * pointer.
+ *
+ * Returns &struct device pointer on success, or ERR_PTR() on error.
+ *
+ * Note: the struct class passed to this function must have previously
+ * been created with a call to class_create().
+ */
+struct device *device_create_vargs(struct class *class, struct device *parent,
+				   dev_t devt, void *drvdata, const char *fmt,
+				   va_list args)
+{
+	return device_create_groups_vargs(class, parent, devt, drvdata, NULL,
+					  fmt, args);
+}
 EXPORT_SYMBOL_GPL(device_create_vargs);
 
 /**
@@ -1767,6 +1778,50 @@ struct device *device_create(struct class *class, struct device *parent,
 }
 EXPORT_SYMBOL_GPL(device_create);
 
+/**
+ * device_create_with_groups - creates a device and registers it with sysfs
+ * @class: pointer to the struct class that this device should be registered to
+ * @parent: pointer to the parent struct device of this new device, if any
+ * @devt: the dev_t for the char device to be added
+ * @drvdata: the data to be added to the device for callbacks
+ * @groups: NULL-terminated list of attribute groups to be created
+ * @fmt: string for the device's name
+ *
+ * This function can be used by char device classes.  A struct device
+ * will be created in sysfs, registered to the specified class.
+ * Additional attributes specified in the groups parameter will also
+ * be created automatically.
+ *
+ * A "dev" file will be created, showing the dev_t for the device, if
+ * the dev_t is not 0,0.
+ * If a pointer to a parent struct device is passed in, the newly created
+ * struct device will be a child of that device in sysfs.
+ * The pointer to the struct device will be returned from the call.
+ * Any further sysfs files that might be required can be created using this
+ * pointer.
+ *
+ * Returns &struct device pointer on success, or ERR_PTR() on error.
+ *
+ * Note: the struct class passed to this function must have previously
+ * been created with a call to class_create().
+ */
+struct device *device_create_with_groups(struct class *class,
+					 struct device *parent, dev_t devt,
+					 void *drvdata,
+					 const struct attribute_group **groups,
+					 const char *fmt, ...)
+{
+	va_list vargs;
+	struct device *dev;
+
+	va_start(vargs, fmt);
+	dev = device_create_groups_vargs(class, parent, devt, drvdata, groups,
+					 fmt, vargs);
+	va_end(vargs);
+	return dev;
+}
+EXPORT_SYMBOL_GPL(device_create_with_groups);
+
 static int __match_devt(struct device *dev, const void *data)
 {
 	const dev_t *devt = data;
include/linux/device.h +5 -0
index f207a8f..bd5931e 100644
@@ -938,6 +938,11 @@ extern __printf(5, 6)
 struct device *device_create(struct class *cls, struct device *parent,
 			     dev_t devt, void *drvdata,
 			     const char *fmt, ...);
+extern __printf(6, 7)
+struct device *device_create_with_groups(struct class *cls,
+			     struct device *parent, dev_t devt, void *drvdata,
+			     const struct attribute_group **groups,
+			     const char *fmt, ...);
 extern void device_destroy(struct class *cls, dev_t devt);
 
 /*
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
author maintainer
#33 lore raw

PATCH v2 7/7 driver core: add default groups to struct class

In reply to Greg Kroah-Hartman

We should be using groups, not attribute lists, for classes to allow subdirectories, and soon, binary files. Groups are just more flexible overall, so add them.

The dev_attrs list will go away after all in-kernel users are converted to use dev_groups.

---
 drivers/base/core.c    | 9 ++++++++-
 include/linux/device.h | 4 +++-
 2 files changed, 11 insertions(+), 2 deletions(-)
drivers/base/core.c +8 -1
index a8aae18..8856d74 100644
@@ -528,9 +528,12 @@ static int device_add_attrs(struct device *dev)
 	int error;
 
 	if (class) {
-		error = device_add_attributes(dev, class->dev_attrs);
+		error = device_add_groups(dev, class->dev_groups);
 		if (error)
 			return error;
+		error = device_add_attributes(dev, class->dev_attrs);
+		if (error)
+			goto err_remove_class_groups;
 		error = device_add_bin_attributes(dev, class->dev_bin_attrs);
 		if (error)
 			goto err_remove_class_attrs;
@@ -563,6 +566,9 @@ static int device_add_attrs(struct device *dev)
  err_remove_class_attrs:
 	if (class)
 		device_remove_attributes(dev, class->dev_attrs);
+ err_remove_class_groups:
+	if (class)
+		device_remove_groups(dev, class->dev_groups);
 
 	return error;
 }
@@ -581,6 +587,7 @@ static void device_remove_attrs(struct device *dev)
 	if (class) {
 		device_remove_attributes(dev, class->dev_attrs);
 		device_remove_bin_attributes(dev, class->dev_bin_attrs);
+		device_remove_groups(dev, class->dev_groups);
 	}
 }
 
include/linux/device.h +3 -1
index bd5931e..22b546a 100644
@@ -320,6 +320,7 @@ int subsys_virtual_register(struct bus_type *subsys,
  * @name:	Name of the class.
  * @owner:	The module owner.
  * @class_attrs: Default attributes of this class.
+ * @dev_groups:	Default attributes of the devices that belong to the class.
  * @dev_attrs:	Default attributes of the devices belong to the class.
  * @dev_bin_attrs: Default binary attributes of the devices belong to the class.
  * @dev_kobj:	The kobject that represents this class and links it into the hierarchy.
@@ -349,7 +350,8 @@ struct class {
 	struct module		*owner;
 
 	struct class_attribute		*class_attrs;
-	struct device_attribute		*dev_attrs;
+	struct device_attribute		*dev_attrs;	/* use dev_groups instead */
+	const struct attribute_group	**dev_groups;
 	struct bin_attribute		*dev_bin_attrs;
 	struct kobject			*dev_kobj;
 
Signature · 1 line
1.8.3.rc0.20.gb99dd2e
Reviewed-by Tested-by on the v2 series
#34 lore raw
In reply to Greg Kroah-Hartman
Quoted 10 lines · Greg Kroah-Hartman

Hi all,

Here's the second iteration of the patchset to add better attribute group support to the driver core and sysfs.

I've tested these (shocker!) and everything works fine with them (I'm sending this from Linus's latest kernel with these 7 on top of it.)

I'd like to send these to Linus for 3.11 unless someone objects.

Quoted 9 lines

Oliver, please use this series instead of the last one, it has fixes that Guenter pointed out that would have crashed your box at boot.

changes from v2:
- actually boots
- 7th patch added properly
- added BUS_ATTR, CLASS_ATTR, and DRIVER_ATTR RW and RO macros to help with converting code to use attributes properly.

Looks good this time. And, yes, it does boot and work, including patch #7. Feel free to add

and if you like

to the series.

Thanks,
Guenter

author maintainer
#35 lore raw
Quoted 23 lines · Guenter Roeck
Quoted 10 lines · Greg Kroah-Hartman

Hi all,

Here's the second iteration of the patchset to add better attribute group support to the driver core and sysfs.

I've tested these (shocker!) and everything works fine with them (I'm sending this from Linus's latest kernel with these 7 on top of it.)

I'd like to send these to Linus for 3.11 unless someone objects.

Quoted 9 lines

Oliver, please use this series instead of the last one, it has fixes that Guenter pointed out that would have crashed your box at boot.

changes from v2:
- actually boots
- 7th patch added properly
- added BUS_ATTR, CLASS_ATTR, and DRIVER_ATTR RW and RO macros to help with converting code to use attributes properly.

Looks good this time. And, yes, it does boot and work, including patch #7. Feel free to add

Quoted 7 lines

and if you like

to the series.

Thanks for the testing and review, I'll add this when I commit them sometime next week.

greg k-h

#36 lore raw
Quoted 7 lines · Greg Kroah-Hartman
Quoted 6 lines · Guenter Roeck
Quoted 5 lines · Greg Kroah-Hartman

Hi all,

Here's the second iteration of the patchset to add better attribute group support to the driver core and sysfs.

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

I've tested these (shocker!) and everything works fine with them (I'm sending this from Linus's latest kernel with these 7 on top of it.)

I'd like to send these to Linus for 3.11 unless someone objects.

Oliver, please use this series instead of the last one, it has fixes that Guenter pointed out that would have crashed your box at boot.

It still crashes, but haven't read back all. I do have some extra helper macro's patch incoming once i make sure it boots.

(it boots but segfaults) give me a few hours to report back.

oliver

Quoted 23 lines
Quoted 10 lines
Quoted 7 lines

changes from v2:
- actually boots
- 7th patch added properly
- added BUS_ATTR, CLASS_ATTR, and DRIVER_ATTR RW and RO macros to help with converting code to use attributes properly.

Looks good this time. And, yes, it does boot and work, including patch #7. Feel free to add

Quoted 7 lines

and if you like

to the series.

Thanks for the testing and review, I'll add this when I commit them sometime next week.

greg k-h

#37 lore raw
In reply to Greg Kroah-Hartman
Quoted 10 lines · Greg Kroah-Hartman

Hi all,

Here's the second iteration of the patchset to add better attribute group support to the driver core and sysfs.

I've tested these (shocker!) and everything works fine with them (I'm sending this from Linus's latest kernel with these 7 on top of it.)

I'd like to send these to Linus for 3.11 unless someone objects.

Hi Greg,

I have not seen the series in the upstream kernel. Do you have an updated plan to get it upstream ?

If needed I can carry the patches I need in my branch for now, so it doesn't matter too much if the code misses 3.11. Still, it would help to know the plan going forward.

Thanks,
Guenter

author maintainer
#38 lore raw
Quoted 11 lines · Guenter Roeck
Quoted 10 lines · Greg Kroah-Hartman

Hi all,

Here's the second iteration of the patchset to add better attribute group support to the driver core and sysfs.

I've tested these (shocker!) and everything works fine with them (I'm sending this from Linus's latest kernel with these 7 on top of it.)

I'd like to send these to Linus for 3.11 unless someone objects.

Quoted 8 lines

Hi Greg,

I have not seen the series in the upstream kernel. Do you have an updated plan to get it upstream ?

If needed I can carry the patches I need in my branch for now, so it doesn't matter too much if the code misses 3.11. Still, it would help to know the plan going forward.

I was planning on doing one more respin of the patches on Monday, and then getting them into 3.11-rc2 if possible so that everyone can start taking advantage of them.

Got sucked into the "discussion" of the stable kernels on Friday and didn't do the update like I was wanting to do so :)

thanks,

greg k-h

#39 lore raw
Quoted 17 lines · Greg Kroah-Hartman
Quoted 16 lines · Guenter Roeck
Quoted 10 lines · Greg Kroah-Hartman

Hi all,

Here's the second iteration of the patchset to add better attribute group support to the driver core and sysfs.

I've tested these (shocker!) and everything works fine with them (I'm sending this from Linus's latest kernel with these 7 on top of it.)

I'd like to send these to Linus for 3.11 unless someone objects.

Hi Greg,

I have not seen the series in the upstream kernel. Do you have an updated plan to get it upstream ?

Quoted 8 lines
Quoted 3 lines

If needed I can carry the patches I need in my branch for now, so it doesn't matter too much if the code misses 3.11. Still, it would help to know the plan going forward.

I was planning on doing one more respin of the patches on Monday, and then getting them into 3.11-rc2 if possible so that everyone can start taking advantage of them.

Sounds good.

Quoted 3 lines

Got sucked into the "discussion" of the stable kernels on Friday and didn't do the update like I was wanting to do so :)

In this context ... you are doing an amazing job with -stable. I have no idea how you manage to do that, especially with all your other responsibilities. If anything, it is unfair to talk about an allegedly "broken" process if so much of it depends on a single person. stable_kernel_rules talks about a review committee. Unless I am missing something, that committee consists of one person. Maybe it would help to add a couple more. Good candidates might be the people who are complaining about a broken process ;).

Guenter