Skip to contentSkip to conversation

0/2 use sysfs bus dev_attrs for scsi_device attributes

PATCH New Patrick Mansfield 4 participants 13 messages Mar 2, 2005 – Apr 6, 2005

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 0/2 use sysfs bus dev_attrs for scsi_device attributes

A couple patches so that when pending changes to sysfs/hotplug are made, patches discussed here:

	http://marc.theaimsgroup.com/?t=110939742700002&r=1&w=2

We will get the hotplug event for a scsi_device only after all the default scsi_device attributes are created.

The removal of the attr_changed_internally() was done so queue_type can more easily be used as a default attribute (using the bus dev_attrs, there is no way for some devices to create it read only, and for others to create it as read write).

Tested with qla2300 and qla1280 drivers - neither currently support writable queue_depth or queue_type.

The attr_overridden (and post these patches, scsi_sysfs_sdev_attrs) should someday be removed, the only attribute being overridden (versus a host specific scsi_device attribute) today is queue_depth, and we have shost->change_queue_depth that can be used instead.

-- Patrick Mansfield

#1 lore raw

PATCH 1/1 1/2 remove attr_changed_internally

Get rid of the attr_changed_internally(), and always create queue_type and queue_depth as read/write, and then writes fail if not supported.

drivers/scsi/scsi_sysfs.c +39 -57
@@ -312,7 +312,6 @@
  * Create the actual show/store functions and data structures.
  */
 sdev_rd_attr (device_blocked, "%d\n");
-sdev_rd_attr (queue_depth, "%d\n");
 sdev_rd_attr (type, "%d\n");
 sdev_rd_attr (scsi_level, "%d\n");
 sdev_rd_attr (vendor, "%.8s\n");
@@ -392,41 +391,9 @@
 
 static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
 
-static ssize_t
-show_queue_type_field(struct device *dev, char *buf)
-{
-	struct scsi_device *sdev = to_scsi_device(dev);
-	const char *name = "none";
-
-	if (sdev->ordered_tags)
-		name = "ordered";
-	else if (sdev->simple_tags)
-		name = "simple";
-
-	return snprintf(buf, 20, "%s\n", name);
-}
-
-static DEVICE_ATTR(queue_type, S_IRUGO, show_queue_type_field, NULL);
-
-
-/* Default template for device attributes.  May NOT be modified */
-static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
-	&dev_attr_device_blocked,
-	&dev_attr_queue_depth,
-	&dev_attr_queue_type,
-	&dev_attr_type,
-	&dev_attr_scsi_level,
-	&dev_attr_vendor,
-	&dev_attr_model,
-	&dev_attr_rev,
-	&dev_attr_rescan,
-	&dev_attr_delete,
-	&dev_attr_state,
-	&dev_attr_timeout,
-	NULL
-};
+sdev_show_function (queue_depth, "%d\n");
 
-static ssize_t sdev_store_queue_depth_rw(struct device *dev, const char *buf,
+static ssize_t sdev_store_queue_depth(struct device *dev, const char *buf,
 					 size_t count)
 {
 	int depth, retval;
@@ -448,11 +415,25 @@
 	return count;
 }
 
-static struct device_attribute sdev_attr_queue_depth_rw =
+static struct device_attribute dev_attr_queue_depth =
 	__ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
-	       sdev_store_queue_depth_rw);
+	       sdev_store_queue_depth);
 
-static ssize_t sdev_store_queue_type_rw(struct device *dev, const char *buf,
+static ssize_t
+show_queue_type_field(struct device *dev, char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	const char *name = "none";
+
+	if (sdev->ordered_tags)
+		name = "ordered";
+	else if (sdev->simple_tags)
+		name = "simple";
+
+	return snprintf(buf, 20, "%s\n", name);
+}
+
+static ssize_t sdev_store_queue_type(struct device *dev, const char *buf,
 					size_t count)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
@@ -480,23 +461,26 @@
 	return count;
 }
 
-static struct device_attribute sdev_attr_queue_type_rw =
+static struct device_attribute dev_attr_queue_type =
 	__ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
-	       sdev_store_queue_type_rw);
-
-static struct device_attribute *attr_changed_internally(
-		struct Scsi_Host *shost,
-		struct device_attribute * attr)
-{
-	if (!strcmp("queue_depth", attr->attr.name)
-	    && shost->hostt->change_queue_depth)
-		return &sdev_attr_queue_depth_rw;
-	else if (!strcmp("queue_type", attr->attr.name)
-	    && shost->hostt->change_queue_type)
-		return &sdev_attr_queue_type_rw;
-	return attr;
-}
+	       sdev_store_queue_type);
 
+/* Default template for device attributes.  May NOT be modified */
+static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
+	&dev_attr_device_blocked,
+	&dev_attr_queue_depth,
+	&dev_attr_queue_type,
+	&dev_attr_type,
+	&dev_attr_scsi_level,
+	&dev_attr_vendor,
+	&dev_attr_model,
+	&dev_attr_rev,
+	&dev_attr_rescan,
+	&dev_attr_delete,
+	&dev_attr_state,
+	&dev_attr_timeout,
+	NULL
+};
 
 static struct device_attribute *attr_overridden(
 		struct device_attribute **attrs,
@@ -602,10 +586,8 @@
 	for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) {
 		if (!attr_overridden(sdev->host->hostt->sdev_attrs,
 					scsi_sysfs_sdev_attrs[i])) {
-			struct device_attribute * attr = 
-				attr_changed_internally(sdev->host, 
-							scsi_sysfs_sdev_attrs[i]);
-			error = device_create_file(&sdev->sdev_gendev, attr);
+			error = device_create_file(&sdev->sdev_gendev,
+						   scsi_sysfs_sdev_attrs[i]);
 			if (error) {
 				scsi_remove_device(sdev);
 				goto out;
#2 lore raw

PATCH 1/1 2/2 Use bus dev_attrs to create scsi_device attributes

Use bus dev_attrs to create the default scsi_device attributes.

Note sdev_default_attrs is not a pointer to an array (like scsi_sysfs_sdev_attrs), and so DEVICE_ATTR's can be removed, and __ATTR used instaed.

drivers/scsi/scsi_sysfs.c renamed from drivers/scsi/s1-scsi_sysfs.c +63 -66
@@ -193,40 +193,6 @@
 	.release	= scsi_device_cls_release,
 };
 
-/* all probing is done in the individual ->probe routines */
-static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
-{
-	struct scsi_device *sdp = to_scsi_device(dev);
-	if (sdp->no_uld_attach)
-		return 0;
-	return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
-}
-
-struct bus_type scsi_bus_type = {
-        .name		= "scsi",
-        .match		= scsi_bus_match,
-};
-
-int scsi_sysfs_register(void)
-{
-	int error;
-
-	error = bus_register(&scsi_bus_type);
-	if (!error) {
-		error = class_register(&sdev_class);
-		if (error)
-			bus_unregister(&scsi_bus_type);
-	}
-
-	return error;
-}
-
-void scsi_sysfs_unregister(void)
-{
-	class_unregister(&sdev_class);
-	bus_unregister(&scsi_bus_type);
-}
-
 /*
  * sdev_show_function: macro to create an attr function that can be used to
  * show a non-bit field.
@@ -245,8 +211,7 @@
  * read only field.
  */
 #define sdev_rd_attr(field, format_string)				\
-	sdev_show_function(field, format_string)			\
-static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL);
+	sdev_show_function(field, format_string)
 
 
 /*
@@ -263,8 +228,7 @@
 	sdev = to_scsi_device(dev);					\
 	snscanf (buf, 20, format_string, &sdev->field);			\
 	return count;							\
-}									\
-static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
+}
 
 /* Currently we don't export bit fields, but we might in future,
  * so leave this code in */
@@ -288,8 +252,7 @@
 		ret = count;						\
 	}								\
 	return ret;							\
-}									\
-static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
+}
 
 /*
  * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
@@ -336,15 +299,13 @@
 	sdev->timeout = timeout * HZ;
 	return count;
 }
-static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
 
 static ssize_t
-store_rescan_field (struct device *dev, const char *buf, size_t count) 
+sdev_store_rescan (struct device *dev, const char *buf, size_t count) 
 {
 	scsi_rescan_device(dev);
 	return count;
 }
-static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
 
 static ssize_t sdev_store_delete(struct device *dev, const char *buf,
 				 size_t count)
@@ -352,10 +313,9 @@
 	scsi_remove_device(to_scsi_device(dev));
 	return count;
 };
-static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
 
 static ssize_t
-store_state_field(struct device *dev, const char *buf, size_t count)
+sdev_store_state(struct device *dev, const char *buf, size_t count)
 {
 	int i;
 	struct scsi_device *sdev = to_scsi_device(dev);
@@ -378,7 +338,7 @@
 }
 
 static ssize_t
-show_state_field(struct device *dev, char *buf)
+sdev_show_state(struct device *dev, char *buf)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
 	const char *name = scsi_device_state_name(sdev->sdev_state);
@@ -389,8 +349,6 @@
 	return snprintf(buf, 20, "%s\n", name);
 }
 
-static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
-
 sdev_show_function (queue_depth, "%d\n");
 
 static ssize_t sdev_store_queue_depth(struct device *dev, const char *buf,
@@ -420,7 +378,7 @@
 	       sdev_store_queue_depth);
 
 static ssize_t
-show_queue_type_field(struct device *dev, char *buf)
+sdev_show_queue_type(struct device *dev, char *buf)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
 	const char *name = "none";
@@ -461,25 +419,29 @@
 	return count;
 }
 
-static struct device_attribute dev_attr_queue_type =
-	__ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
-	       sdev_store_queue_type);
+#define SDEV_ATTR_RO(_name) __ATTR(_name, S_IRUGO, sdev_show_##_name, NULL)
+#define SDEV_ATTR_WO(_name) __ATTR(_name, S_IWUSR, NULL, sdev_store_##_name)
+#define SDEV_ATTR_RW(_name) __ATTR(_name, S_IRUGO | S_IWUSR, \
+				   sdev_show_##_name, sdev_store_##_name)
+
+/* Default scsi_device attributes, cannot be overidden */
+static struct device_attribute sdev_default_attrs[] = {
+	SDEV_ATTR_RO(device_blocked),
+	SDEV_ATTR_RW(queue_type),
+	SDEV_ATTR_RO(type),
+	SDEV_ATTR_RO(scsi_level),
+	SDEV_ATTR_RO(vendor),
+	SDEV_ATTR_RO(model),
+	SDEV_ATTR_RO(rev),
+	SDEV_ATTR_WO(rescan),
+	SDEV_ATTR_WO(delete),
+	SDEV_ATTR_RW(state),
+	SDEV_ATTR_RW(timeout),
+	__ATTR_NULL
+};
 
-/* Default template for device attributes.  May NOT be modified */
 static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
-	&dev_attr_device_blocked,
-	&dev_attr_queue_depth,
-	&dev_attr_queue_type,
-	&dev_attr_type,
-	&dev_attr_scsi_level,
-	&dev_attr_vendor,
-	&dev_attr_model,
-	&dev_attr_rev,
-	&dev_attr_rescan,
-	&dev_attr_delete,
-	&dev_attr_state,
-	&dev_attr_timeout,
-	NULL
+	&dev_attr_queue_depth
 };
 
 static struct device_attribute *attr_overridden(
@@ -518,6 +480,41 @@
 	return device_create_file(dev, attr);
 }
 
+/* all probing is done in the individual ->probe routines */
+static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
+{
+	struct scsi_device *sdp = to_scsi_device(dev);
+	if (sdp->no_uld_attach)
+		return 0;
+	return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
+}
+
+struct bus_type scsi_bus_type = {
+        .name		= "scsi",
+        .match		= scsi_bus_match,
+	.dev_attrs	= sdev_default_attrs,
+};
+
+int scsi_sysfs_register(void)
+{
+	int error;
+
+	error = bus_register(&scsi_bus_type);
+	if (!error) {
+		error = class_register(&sdev_class);
+		if (error)
+			bus_unregister(&scsi_bus_type);
+	}
+
+	return error;
+}
+
+void scsi_sysfs_unregister(void)
+{
+	class_unregister(&sdev_class);
+	bus_unregister(&scsi_bus_type);
+}
+
 static void scsi_target_dev_release(struct device *dev)
 {
 	struct scsi_target *starget = to_scsi_target(dev);
#3 lore raw

Re: [PATCH] 2/2 Use bus dev_attrs to create scsi_device attributes

Quoted 5 lines · Patrick Mansfield

Use bus dev_attrs to create the default scsi_device attributes.

Note sdev_default_attrs is not a pointer to an array (like scsi_sysfs_sdev_attrs), and so DEVICE_ATTR's can be removed, and __ATTR used instaed.

Any comments on this? Should I resend these patches?

Do we need a new driver interface that allows the driver to explicitly send the hotplug after all attributes have been created?

Such a new interface would allow scsi to continue to create attributes (based on the underlying HBA or transport capability) that are sometimes read only, and sometimes read+write. The current driver interface does not allow default attributes to have different read/write properties.

And scsi could keep its current host override ability (we can't use the current override code with the default attributes).

In any case, we need changes so udev can stop waiting for sysfs attributes.

Quoted 220 lines
drivers/scsi/scsi_sysfs.c renamed from drivers/scsi/s1-scsi_sysfs.c +63 -66
@@ -193,40 +193,6 @@
 	.release	= scsi_device_cls_release,
 };
 
-/* all probing is done in the individual ->probe routines */
-static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
-{
-	struct scsi_device *sdp = to_scsi_device(dev);
-	if (sdp->no_uld_attach)
-		return 0;
-	return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
-}
-
-struct bus_type scsi_bus_type = {
-        .name		= "scsi",
-        .match		= scsi_bus_match,
-};
-
-int scsi_sysfs_register(void)
-{
-	int error;
-
-	error = bus_register(&scsi_bus_type);
-	if (!error) {
-		error = class_register(&sdev_class);
-		if (error)
-			bus_unregister(&scsi_bus_type);
-	}
-
-	return error;
-}
-
-void scsi_sysfs_unregister(void)
-{
-	class_unregister(&sdev_class);
-	bus_unregister(&scsi_bus_type);
-}
-
 /*
  * sdev_show_function: macro to create an attr function that can be used to
  * show a non-bit field.
@@ -245,8 +211,7 @@
  * read only field.
  */
 #define sdev_rd_attr(field, format_string)				\
-	sdev_show_function(field, format_string)			\
-static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL);
+	sdev_show_function(field, format_string)
 
 
 /*
@@ -263,8 +228,7 @@
 	sdev = to_scsi_device(dev);					\
 	snscanf (buf, 20, format_string, &sdev->field);			\
 	return count;							\
-}									\
-static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
+}
 
 /* Currently we don't export bit fields, but we might in future,
  * so leave this code in */
@@ -288,8 +252,7 @@
 		ret = count;						\
 	}								\
 	return ret;							\
-}									\
-static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
+}
 
 /*
  * scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
@@ -336,15 +299,13 @@
 	sdev->timeout = timeout * HZ;
 	return count;
 }
-static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
 
 static ssize_t
-store_rescan_field (struct device *dev, const char *buf, size_t count) 
+sdev_store_rescan (struct device *dev, const char *buf, size_t count) 
 {
 	scsi_rescan_device(dev);
 	return count;
 }
-static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
 
 static ssize_t sdev_store_delete(struct device *dev, const char *buf,
 				 size_t count)
@@ -352,10 +313,9 @@
 	scsi_remove_device(to_scsi_device(dev));
 	return count;
 };
-static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
 
 static ssize_t
-store_state_field(struct device *dev, const char *buf, size_t count)
+sdev_store_state(struct device *dev, const char *buf, size_t count)
 {
 	int i;
 	struct scsi_device *sdev = to_scsi_device(dev);
@@ -378,7 +338,7 @@
 }
 
 static ssize_t
-show_state_field(struct device *dev, char *buf)
+sdev_show_state(struct device *dev, char *buf)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
 	const char *name = scsi_device_state_name(sdev->sdev_state);
@@ -389,8 +349,6 @@
 	return snprintf(buf, 20, "%s\n", name);
 }
 
-static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
-
 sdev_show_function (queue_depth, "%d\n");
 
 static ssize_t sdev_store_queue_depth(struct device *dev, const char *buf,
@@ -420,7 +378,7 @@
 	       sdev_store_queue_depth);
 
 static ssize_t
-show_queue_type_field(struct device *dev, char *buf)
+sdev_show_queue_type(struct device *dev, char *buf)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
 	const char *name = "none";
@@ -461,25 +419,29 @@
 	return count;
 }
 
-static struct device_attribute dev_attr_queue_type =
-	__ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field,
-	       sdev_store_queue_type);
+#define SDEV_ATTR_RO(_name) __ATTR(_name, S_IRUGO, sdev_show_##_name, NULL)
+#define SDEV_ATTR_WO(_name) __ATTR(_name, S_IWUSR, NULL, sdev_store_##_name)
+#define SDEV_ATTR_RW(_name) __ATTR(_name, S_IRUGO | S_IWUSR, \
+				   sdev_show_##_name, sdev_store_##_name)
+
+/* Default scsi_device attributes, cannot be overidden */
+static struct device_attribute sdev_default_attrs[] = {
+	SDEV_ATTR_RO(device_blocked),
+	SDEV_ATTR_RW(queue_type),
+	SDEV_ATTR_RO(type),
+	SDEV_ATTR_RO(scsi_level),
+	SDEV_ATTR_RO(vendor),
+	SDEV_ATTR_RO(model),
+	SDEV_ATTR_RO(rev),
+	SDEV_ATTR_WO(rescan),
+	SDEV_ATTR_WO(delete),
+	SDEV_ATTR_RW(state),
+	SDEV_ATTR_RW(timeout),
+	__ATTR_NULL
+};
 
-/* Default template for device attributes.  May NOT be modified */
 static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
-	&dev_attr_device_blocked,
-	&dev_attr_queue_depth,
-	&dev_attr_queue_type,
-	&dev_attr_type,
-	&dev_attr_scsi_level,
-	&dev_attr_vendor,
-	&dev_attr_model,
-	&dev_attr_rev,
-	&dev_attr_rescan,
-	&dev_attr_delete,
-	&dev_attr_state,
-	&dev_attr_timeout,
-	NULL
+	&dev_attr_queue_depth
 };
 
 static struct device_attribute *attr_overridden(
@@ -518,6 +480,41 @@
 	return device_create_file(dev, attr);
 }
 
+/* all probing is done in the individual ->probe routines */
+static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
+{
+	struct scsi_device *sdp = to_scsi_device(dev);
+	if (sdp->no_uld_attach)
+		return 0;
+	return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
+}
+
+struct bus_type scsi_bus_type = {
+        .name		= "scsi",
+        .match		= scsi_bus_match,
+	.dev_attrs	= sdev_default_attrs,
+};
+
+int scsi_sysfs_register(void)
+{
+	int error;
+
+	error = bus_register(&scsi_bus_type);
+	if (!error) {
+		error = class_register(&sdev_class);
+		if (error)
+			bus_unregister(&scsi_bus_type);
+	}
+
+	return error;
+}
+
+void scsi_sysfs_unregister(void)
+{
+	class_unregister(&sdev_class);
+	bus_unregister(&scsi_bus_type);
+}
+
 static void scsi_target_dev_release(struct device *dev)
 {
 	struct scsi_target *starget = to_scsi_target(dev);
#4 lore raw

Re: [PATCH] 2/2 Use bus dev_attrs to create scsi_device attributes

Quoted 1 line · Patrick Mansfield

Any comments on this? Should I resend these patches?

Well, the basic comment is that there are a lot of features that SCSI has that the driver core lacks:

1) Attribute overrides. This is actually part of the published API for SCSI
2) Ability to add extra attributes---several drivers use this
3) Ability to change attribute permissions based on capabilities.

I really rather like all of these features.

Initially when we did all this work for SCSI, there wasn't much enthusiasm for incorporating these features into drivers/base. You could look and see what it would take to do this, and propose it to Greg ... If he's happy, I'd have no problem moving over because now we won't lose any functionality.

James

#5 lore raw

Re: [PATCH] 2/2 Use bus dev_attrs to create scsi_device attributes

Quoted 11 lines · James Bottomley
Quoted 1 line · Patrick Mansfield

Any comments on this? Should I resend these patches?

Well, the basic comment is that there are a lot of features that SCSI has that the driver core lacks:

1) Attribute overrides. This is actually part of the published API for SCSI
2) Ability to add extra attributes---several drivers use this
3) Ability to change attribute permissions based on capabilities.

Quoted 7 lines

I really rather like all of these features.

Initially when we did all this work for SCSI, there wasn't much enthusiasm for incorporating these features into drivers/base. You could look and see what it would take to do this, and propose it to Greg ... If he's happy, I'd have no problem moving over because now we won't lose any functionality.

I would be very interested in seeing the above stuff move into the driver core.

thanks,

greg k-h

#6 lore raw

Re: [PATCH] 2/2 Use bus dev_attrs to create scsi_device attributes

Quoted 7 lines · Greg KH
Quoted 6 lines · James Bottomley
Quoted 1 line · Patrick Mansfield

Any comments on this? Should I resend these patches?

Well, the basic comment is that there are a lot of features that SCSI has that the driver core lacks:

Quoted 6 lines
Quoted 3 lines

1) Attribute overrides. This is actually part of the published API for SCSI
2) Ability to add extra attributes---several drivers use this
3) Ability to change attribute permissions based on capabilities.

I would be very interested in seeing the above stuff move into the driver core.

Point 3) seems to work for me. :)

Thanks,
Kay

---
sysfs: allow change of permissions for already created attributes

===== fs/sysfs/file.c 1.23 vs edited =====

fs/sysfs/file.c +33 -0
@@ -428,6 +428,39 @@ int sysfs_update_file(struct kobject * k
 
 
 /**
+ * sysfs_chmod_file - update the modified mode value on an object attribute.
+ * @kobj: object we're acting for.
+ * @mode: file permissions.
+ *
+ */
+int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr)
+{
+	struct dentry *dir = kobj->dentry;
+	struct dentry *victim;
+	struct sysfs_dirent *sd;
+	umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
+	int res = -ENOENT;
+
+	down(&dir->d_inode->i_sem);
+	victim = sysfs_get_dentry(dir, attr->name);
+	if (!IS_ERR(victim)) {
+		if (victim->d_inode &&
+		    (victim->d_parent->d_inode == dir->d_inode)) {
+			sd = victim->d_fsdata;
+			sd->s_mode = mode;
+			victim->d_inode->i_mode = mode;
+			dput(victim);
+			res = 0;
+		}
+	}
+	up(&dir->d_inode->i_sem);
+
+	return res;
+}
+EXPORT_SYMBOL_GPL(sysfs_chmod_file);
+
+
+/**
  *	sysfs_remove_file - remove an object attribute.
  *	@kobj:	object we're acting for.
  *	@attr:	attribute descriptor.

===== include/linux/sysfs.h 1.39 vs edited =====

include/linux/sysfs.h +7 -0
@@ -99,6 +99,9 @@ sysfs_create_file(struct kobject *, cons
 extern int
 sysfs_update_file(struct kobject *, const struct attribute *);
 
+extern int
+sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr);
+
 extern void
 sysfs_remove_file(struct kobject *, const struct attribute *);
 
@@ -137,6 +140,10 @@ static inline int sysfs_create_file(stru
 }
 
 static inline int sysfs_update_file(struct kobject * k, const struct attribute * a)
+{
+	return 0;
+}
+static inline int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr)
 {
 	return 0;
 }
#7 lore raw

Re: [PATCH] 2/2 Use bus dev_attrs to create scsi_device attributes

Quoted 9 lines · Kay Sievers

---
sysfs: allow change of permissions for already created attributes

===== fs/sysfs/file.c 1.23 vs edited =====

fs/sysfs/file.c int sysfs_update_file(struct kobject * k · line 436

Quoted 9 lines
fs/sysfs/file.c +6 -0
@@ -428,6 +428,39 @@ int sysfs_update_file(struct kobject * k
 
 
 /**
+ * sysfs_chmod_file - update the modified mode value on an object attribute.
+ * @kobj: object we're acting for.
+ * @mode: file permissions.
+ *
+ */
+int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr)

Your documentation doesn't match up with your function arguments :)

Shouldn't you want an extra mode variable? Makes it easier to override than remembering to change the mode in the attribute before calling the function.

thanks,

greg k-h

#8 lore raw

Re: [PATCH] 2/2 Use bus dev_attrs to create scsi_device attributes

Quoted 10 lines · Greg KH
Quoted 7 lines · Kay Sievers

/**
+ * sysfs_chmod_file - update the modified mode value on an object attribute.
+ * @kobj: object we're acting for.
+ * @mode: file permissions.
+ *
+ */
+int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr)

Your documentation doesn't match up with your function arguments :)

Bah, I tried both versions. :)

Quoted 3 lines

Shouldn't you want an extra mode variable? Makes it easier to override than remembering to change the mode in the attribute before calling the function.

If that's better, sure. Here is a new patch.

Thanks,
Kay

---
sysfs: allow changing the permissions for already created attributes

===== fs/sysfs/file.c 1.23 vs edited =====

fs/sysfs/file.c +35 -0
@@ -428,6 +428,41 @@ int sysfs_update_file(struct kobject * k
 
 
 /**
+ * sysfs_chmod_file - update the modified mode value on an object attribute.
+ * @kobj: object we're acting for.
+ * @attr: attribute descriptor.
+ * @mode: file permissions.
+ *
+ */
+int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
+{
+	struct dentry *dir = kobj->dentry;
+	struct dentry *victim;
+	struct sysfs_dirent *sd;
+	umode_t umode = (mode & S_IALLUGO) | S_IFREG;
+	int res = -ENOENT;
+
+	down(&dir->d_inode->i_sem);
+	victim = sysfs_get_dentry(dir, attr->name);
+	if (!IS_ERR(victim)) {
+		if (victim->d_inode &&
+		    (victim->d_parent->d_inode == dir->d_inode)) {
+			sd = victim->d_fsdata;
+			attr->mode = mode;
+			sd->s_mode = umode;
+			victim->d_inode->i_mode = umode;
+			dput(victim);
+			res = 0;
+		}
+	}
+	up(&dir->d_inode->i_sem);
+
+	return res;
+}
+EXPORT_SYMBOL_GPL(sysfs_chmod_file);
+
+
+/**
  *	sysfs_remove_file - remove an object attribute.
  *	@kobj:	object we're acting for.
  *	@attr:	attribute descriptor.

===== include/linux/sysfs.h 1.39 vs edited =====

include/linux/sysfs.h +7 -0
@@ -99,6 +99,9 @@ sysfs_create_file(struct kobject *, cons
 extern int
 sysfs_update_file(struct kobject *, const struct attribute *);
 
+extern int
+sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode);
+
 extern void
 sysfs_remove_file(struct kobject *, const struct attribute *);
 
@@ -137,6 +140,10 @@ static inline int sysfs_create_file(stru
 }
 
 static inline int sysfs_update_file(struct kobject * k, const struct attribute * a)
+{
+	return 0;
+}
+static inline int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
 {
 	return 0;
 }
#9 lore raw

Re: [PATCH] 2/2 Use bus dev_attrs to create scsi_device attributes

Quoted 12 lines · Kay Sievers
Quoted 10 lines · Greg KH
Quoted 7 lines · Kay Sievers

/**
+ * sysfs_chmod_file - update the modified mode value on an object attribute.
+ * @kobj: object we're acting for.
+ * @mode: file permissions.
+ *
+ */
+int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr)

Your documentation doesn't match up with your function arguments :)

Quoted 7 lines

Bah, I tried both versions. :)

Quoted 3 lines

Shouldn't you want an extra mode variable? Makes it easier to override than remembering to change the mode in the attribute before calling the function.

If that's better, sure. Here is a new patch.

Looks good, applied to my tree.

thanks,

greg k-h

#10 lore raw

Re: [PATCH] 2/2 Use bus dev_attrs to create scsi_device attributes

In reply to James Bottomley
Quoted 7 lines · James Bottomley
Quoted 1 line · Patrick Mansfield

Any comments on this? Should I resend these patches?

Well, the basic comment is that there are a lot of features that SCSI has that the driver core lacks:

1) Attribute overrides. This is actually part of the published API for SCSI

What does this exactly mean? Handle the same attribute dynamically with a different source of data?

Quoted 1 line

2) Ability to add extra attributes---several drivers use this

What is missing in the driver core here? Why can't you add/remove attribute files at any time?

Thanks,
Kay

#11 lore raw

Re: [PATCH] 2/2 Use bus dev_attrs to create scsi_device attributes

Quoted 11 lines · Kay Sievers
Quoted 7 lines · James Bottomley
Quoted 1 line · Patrick Mansfield

Any comments on this? Should I resend these patches?

Well, the basic comment is that there are a lot of features that SCSI has that the driver core lacks:

1) Attribute overrides. This is actually part of the published API for SCSI

What does this exactly mean? Handle the same attribute dynamically with a different source of data?

Well a different function handled by the host driver, rather than the function in scsi core, for example, the twa_queue_depth_attr in drivers/scsi/3w-9xxx.c overrides the simple read attr function in scsi_syfs.c created via this line:

	sdev_rd_attr (queue_depth, "%d\n").  

The patch left this in but only for queue_depth, not for all of the scsi_devie attributes. We have sht->change_queue_depth that can already handle this, some drivers use it, but some still use the sdev_attrs to override the queue_depth. IMO, we should get rid of the override, James doesn't agree.

James - are you OK with allowing only specific overrides of attributes?

Quoted 4 lines
Quoted 1 line

2) Ability to add extra attributes---several drivers use this

What is missing in the driver core here? Why can't you add/remove attribute files at any time?

The patch left this alone, but should be changed to make sure duplicate (that we can't override) attributes get errors. It is just a nice way for host adapters to add attributes to a scsi_device.

But, for any of these non bus_attr and class attributes, the hotplug notification (for scsi_device or the upper level block/char device) will still come before the attributes are created. This is also true for the transport attributes. This is a potential problem, I know of no udev program or hotplug helpers that use any of these attributes.

I see no easy way around this problem without a multi-step registration, like a device_init(), device_ready(). So a device_add would just be:

device_init()
device_ready()

Is your kobject_hotplug patch still pending?

We also need the following, else dev_attrs will show up after the probe and hotplug event for a matching driver (for example, an sd block hotplug event is generated via the device_attach() call). This could be causing problems today, AFAIR you already hack around this problem in udev.

drivers/base/bus.c renamed from drivers/base/orig-bus.c +3 -3
@@ -458,14 +458,14 @@ int bus_add_device(struct device * dev)
 	int error = 0;
 
 	if (bus) {
+		device_add_attrs(bus, dev);
+		sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
+		sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
 		down_write(&dev->bus->subsys.rwsem);
 		pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
 		list_add_tail(&dev->bus_list, &dev->bus->devices.list);
 		device_attach(dev);
 		up_write(&dev->bus->subsys.rwsem);
-		device_add_attrs(bus, dev);
-		sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
-		sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
 	}
 	return error;
 }

-- Patrick Mansfield

#12 lore raw

Re: [PATCH] 2/2 Use bus dev_attrs to create scsi_device attributes

Quoted 20 lines · Patrick Mansfield
Quoted 11 lines · Kay Sievers
Quoted 7 lines · James Bottomley
Quoted 1 line · Patrick Mansfield

Any comments on this? Should I resend these patches?

Well, the basic comment is that there are a lot of features that SCSI has that the driver core lacks:

1) Attribute overrides. This is actually part of the published API for SCSI

What does this exactly mean? Handle the same attribute dynamically with a different source of data?

Well a different function handled by the host driver, rather than the function in scsi core, for example, the twa_queue_depth_attr in drivers/scsi/3w-9xxx.c overrides the simple read attr function in scsi_syfs.c created via this line:

	sdev_rd_attr (queue_depth, "%d\n").  
Quoted 7 lines

The patch left this in but only for queue_depth, not for all of the scsi_devie attributes. We have sht->change_queue_depth that can already handle this, some drivers use it, but some still use the sdev_attrs to override the queue_depth. IMO, we should get rid of the override, James doesn't agree.

James - are you OK with allowing only specific overrides of attributes?

Ok, I see. But how could that be solved in the core. By allowing to override the sysfs-operations of already created attributes instead of letting scsi dispatch these calls itself?

Quoted 9 lines
Quoted 4 lines
Quoted 1 line

2) Ability to add extra attributes---several drivers use this

What is missing in the driver core here? Why can't you add/remove attribute files at any time?

The patch left this alone, but should be changed to make sure duplicate (that we can't override) attributes get errors. It is just a nice way for host adapters to add attributes to a scsi_device.

Quoted 5 lines

But, for any of these non bus_attr and class attributes, the hotplug notification (for scsi_device or the upper level block/char device) will still come before the attributes are created. This is also true for the transport attributes. This is a potential problem, I know of no udev program or hotplug helpers that use any of these attributes.

I was thinking about adding a special key to udev that will wait for a attribute to show up. Just like the wait_for_sysfs logic we do today, but only triggered by a explicit rule-key. In that case a user of that attribute would need to add a rule to wait for a specific attribute.

Quoted 7 lines

I see no easy way around this problem without a multi-step registration, like a device_init(), device_ready(). So a device_add would just be:

device_init()
device_ready()

Is your kobject_hotplug patch still pending?

It's im -mm now.

Quoted 4 lines

We also need the following, else dev_attrs will show up after the probe and hotplug event for a matching driver (for example, an sd block hotplug event is generated via the device_attach() call). This could be causing problems today, AFAIR you already hack around this problem in udev.

If that is possible, it would be nice, so we can get rid of the hard-coded lists in udev, that are doing stat() loops at event time until the attribute arrives.

Thanks,
Kay