[RFC-patch] pc87360 - unchecked rc=device_create_file() fixes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jean Delvare wrote:
> Hi Jim, Mark,
>
>   
hi guys
> Sorry for the late answer, I have a hard time catching up with e-mail
> since I returned from vacation.
>
>   
>>> - changing strategy  from completely-unchecked to 
>>> undo-everything-and-bailout
>>>    is a rather long step, and makes driver possibly unusable in some 
>>> corner cases
>>>    (none of which we know and can repeat)
>>>       
>> True enough, but I imagine that any other solution will be frowned upon
>> as "wallpapering over bugs".  Jean: any opinion on this?
>>     
>
> Yup, I don't much like Jim's approach, because it's meant to be
> temporary. Mark's approach seems better, especially since it is less
> difficult than I first thought. Now let's see how it scales to more
> complex drivers. Jim, would you like to try implementing something
> similar for the pc87360 driver (or any other complex driver of your
> choice, as long as you can test it) and see how it goes?
>
>   
Im completely impressed by how clean Mark's patch is.
In the end, the elegance seduced me, patch follows.

in the start, I cut-pasted my own remove-bunch/group.
its if-0'd now, to be yanked..

In contrast with Mark's declarative grouping, Im doing it at runtime:
     pc87360_detect()
            calls add_tothe_group() to add it to one_big_group[] for 
each sensor-attr wanted,
             then calls sysfs_create_group()

NB - the var and fn names are chosen to convey the implicit context,
and some sheepishness on my part for the obvious laziness ;-)
OTOH - all the implicit-ness is in the 1st 30 lines of the patch.


I thought about trying to generalize the fn a bit better :
    sysfs_addto_group( attr_group, new_attr);

but that seemed to imply promises about a dynamically allocated (and 
resized) group,
which probly should be done as a real LIST or something, but I wanted 
static allocation
(ENOUGH_ATTRS) since the driver has *only* statically declared attributes.

Its probly worth noting that pc87360 now does:    hwmon_register b4 
sysfs_create_group
whereas Mark's patch does the opposite.   Does this matter ??


Ive left a few other comments in the code...


diff -ruNp -X dontdiff -X exclude-diffs ../linux-2.6.18-rc3-sk/drivers/hwmon/pc87360.c sysdev/drivers/hwmon/pc87360.c
--- ../linux-2.6.18-rc3-sk/drivers/hwmon/pc87360.c	2006-06-17 19:49:35.000000000 -0600
+++ sysdev/drivers/hwmon/pc87360.c	2006-08-03 12:58:29.000000000 -0600
@@ -829,6 +829,83 @@ static int __init pc87360_find(int sioad
 	return 0;
 }
 
+/* Declare and use an attribute-group for simplicity.
+   This driver declares all attributes statically, so we count uses of 
+   SENSOR_ATTR, DEVICE_ATTR, and add 1 space for trailing NULL (+0 fudge)
+*/
+#define ENOUGH_ATTRS	89 + 4 + 1 + 0
+static struct attribute *one_big_group[ENOUGH_ATTRS];
+static int next_member;
+
+static struct attribute_group my_group = {
+	.attrs = one_big_group
+};
+
+static void add_tothe_group(struct device *dev,
+				struct device_attribute *devattr)
+{
+	/* add attr to the group for later sysfs_create_group */
+	if (next_member < ENOUGH_ATTRS)
+		one_big_group[next_member++] = &devattr->attr;
+	else {
+		BUG_ON("too many in group for static alloc!\n");
+		dev_err(dev, "too many in group for static alloc!\n");
+	}
+}
+
+#if 0
+static void remove_all_devattr_files(struct device *dev)
+{
+	int i;
+	/* Mark Hoffman used sysfs_remove_group here, it nicely tracks
+	   group membership, at cost of array of pointers.  For now,
+	   stick w non-group approach - cost is cut-paste in-elegance
+	   & maint if sensor set changes */
+
+	dev_info(dev, "created %d attr-files, w errs %d.  now destroying\n",
+		 next_member, devattr_file_create_errs);
+
+	/* tiny cheat - rely on size equivalence of {type}_{attr}[]
+	   arrays across all attrs for each type (declared that way)
+	*/
+	for (i = 0; i < ARRAY_SIZE(in_input); i++) {
+		device_remove_file(dev, &in_input[i].dev_attr);
+		device_remove_file(dev, &in_min[i].dev_attr);
+		device_remove_file(dev, &in_max[i].dev_attr);
+		device_remove_file(dev, &in_status[i].dev_attr);
+	}
+	device_remove_file(dev, &dev_attr_cpu0_vid);
+	device_remove_file(dev, &dev_attr_vrm);
+	device_remove_file(dev, &dev_attr_alarms_in);
+
+	for (i = 0; i < ARRAY_SIZE(temp_input); i++) {
+		device_remove_file(dev, &temp_input[i].dev_attr);
+		device_remove_file(dev, &temp_min[i].dev_attr);
+		device_remove_file(dev, &temp_max[i].dev_attr);
+		device_remove_file(dev, &temp_crit[i].dev_attr);
+		device_remove_file(dev, &temp_status[i].dev_attr);
+	}
+	device_remove_file(dev, &dev_attr_alarms_temp);
+
+	for (i = 0; i < ARRAY_SIZE(therm_input); i++) {
+		device_remove_file(dev, &therm_input[i].dev_attr);
+		device_remove_file(dev, &therm_min[i].dev_attr);
+		device_remove_file(dev, &therm_max[i].dev_attr);
+		device_remove_file(dev, &therm_crit[i].dev_attr);
+		device_remove_file(dev, &therm_status[i].dev_attr);
+	}
+	for (i = 0; i < ARRAY_SIZE(fan_input); i++) {
+		device_remove_file(dev, &fan_input[i].dev_attr);
+		device_remove_file(dev, &fan_min[i].dev_attr);
+		device_remove_file(dev, &fan_div[i].dev_attr);
+		device_remove_file(dev, &fan_status[i].dev_attr);
+		device_remove_file(dev, &pwm[i].dev_attr);
+	}
+
+	dev_info(dev, "remaining attr-files %d\n", next_member);
+}
+#endif
+
 static int pc87360_detect(struct i2c_adapter *adapter)
 {
 	int i;
@@ -944,50 +1021,61 @@ static int pc87360_detect(struct i2c_ada
 
 	if (data->innr) {
 		for (i = 0; i < 11; i++) {
-			device_create_file(dev, &in_input[i].dev_attr);
-			device_create_file(dev, &in_min[i].dev_attr);
-			device_create_file(dev, &in_max[i].dev_attr);
-			device_create_file(dev, &in_status[i].dev_attr);
-		}
-		device_create_file(dev, &dev_attr_cpu0_vid);
-		device_create_file(dev, &dev_attr_vrm);
-		device_create_file(dev, &dev_attr_alarms_in);
+			add_tothe_group(dev, &in_input[i].dev_attr);
+			add_tothe_group(dev, &in_min[i].dev_attr);
+			add_tothe_group(dev, &in_max[i].dev_attr);
+			add_tothe_group(dev, &in_status[i].dev_attr);
+		}
+		add_tothe_group(dev, &dev_attr_cpu0_vid);
+		add_tothe_group(dev, &dev_attr_vrm);
+		add_tothe_group(dev, &dev_attr_alarms_in);
 	}
 
 	if (data->tempnr) {
 		for (i = 0; i < data->tempnr; i++) {
-			device_create_file(dev, &temp_input[i].dev_attr);
-			device_create_file(dev, &temp_min[i].dev_attr);
-			device_create_file(dev, &temp_max[i].dev_attr);
-			device_create_file(dev, &temp_crit[i].dev_attr);
-			device_create_file(dev, &temp_status[i].dev_attr);
+			add_tothe_group(dev, &temp_input[i].dev_attr);
+			add_tothe_group(dev, &temp_min[i].dev_attr);
+			add_tothe_group(dev, &temp_max[i].dev_attr);
+			add_tothe_group(dev, &temp_crit[i].dev_attr);
+			add_tothe_group(dev, &temp_status[i].dev_attr);
 		}
-		device_create_file(dev, &dev_attr_alarms_temp);
+		add_tothe_group(dev, &dev_attr_alarms_temp);
 	}
 
 	if (data->innr == 14) {
 		for (i = 0; i < 3; i++) {
-			device_create_file(dev, &therm_input[i].dev_attr);
-			device_create_file(dev, &therm_min[i].dev_attr);
-			device_create_file(dev, &therm_max[i].dev_attr);
-			device_create_file(dev, &therm_crit[i].dev_attr);
-			device_create_file(dev, &therm_status[i].dev_attr);
+			add_tothe_group(dev, &therm_input[i].dev_attr);
+			add_tothe_group(dev, &therm_min[i].dev_attr);
+			add_tothe_group(dev, &therm_max[i].dev_attr);
+			add_tothe_group(dev, &therm_crit[i].dev_attr);
+			add_tothe_group(dev, &therm_status[i].dev_attr);
 		}
 	}
 
 	for (i = 0; i < data->fannr; i++) {
 		if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
-			device_create_file(dev, &fan_input[i].dev_attr);
-			device_create_file(dev, &fan_min[i].dev_attr);
-			device_create_file(dev, &fan_div[i].dev_attr);
-			device_create_file(dev, &fan_status[i].dev_attr);
+			add_tothe_group(dev, &fan_input[i].dev_attr);
+			add_tothe_group(dev, &fan_min[i].dev_attr);
+			add_tothe_group(dev, &fan_div[i].dev_attr);
+			add_tothe_group(dev, &fan_status[i].dev_attr);
 		}
 		if (FAN_CONFIG_CONTROL(data->fan_conf, i))
-			device_create_file(dev, &pwm[i].dev_attr);
+			add_tothe_group(dev, &pwm[i].dev_attr);
 	}
 
+	/* Register sysfs hooks for the group */
+	err = sysfs_create_group(&client->dev.kobj, &my_group);
+	if (err) {
+		dev_err(&client->dev, "group-create failed: %d, %d members\n",
+			err, next_member);
+		goto ERROR3;
+	}
+	
 	return 0;
 
+	/* ERROR4:
+	   sysfs_remove_group(&client->dev.kobj, &my_group);
+	*/
 ERROR3:
 	i2c_detach_client(client);
 ERROR2:
@@ -1006,6 +1094,7 @@ static int pc87360_detach_client(struct 
 	struct pc87360_data *data = i2c_get_clientdata(client);
 	int i;
 
+	sysfs_remove_group(&client->dev.kobj, &my_group);
 	hwmon_device_unregister(data->class_dev);
 
 	if ((i = i2c_detach_client(client)))






[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux