]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] sysfs module unload race fix for bin_attributes
authorMichael E. Brown <mebrown@michaels-house.net>
Thu, 22 Apr 2004 05:19:51 +0000 (22:19 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 22 Apr 2004 05:19:51 +0000 (22:19 -0700)
 -  Add module locking to sysfs bin_attribute files. Update all in-tree
    users to set module owner.

Compile tested. booted. stress tests pass:

while true; do modprobe mymod; rmmod mymod; done &
while true; do hexdump -C /sys/path/to/sysfs/binary/file; done

drivers/base/firmware_class.c
drivers/i2c/chips/eeprom.c
drivers/scsi/qla2xxx/qla_os.c
fs/sysfs/bin.c

index 696038e7b34c65073dba19bdf2d2e6bee8233b32..8ff239f146cfd02c996e2c4427795bfb103909fc 100644 (file)
@@ -254,7 +254,7 @@ out:
        return retval;
 }
 static struct bin_attribute firmware_attr_data_tmpl = {
-       .attr = {.name = "data", .mode = 0644},
+       .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
        .size = 0,
        .read = firmware_data_read,
        .write = firmware_data_write,
index 21fa361344cf9dbae567e9f444f1a08fd08b289d..5d1492ac4217198ed65fc1bd9d290283fedf0100 100644 (file)
@@ -155,6 +155,7 @@ static struct bin_attribute eeprom_attr = {
        .attr = {
                .name = "eeprom",
                .mode = S_IRUGO,
+               .owner = THIS_MODULE,
        },
        .size = EEPROM_SIZE,
        .read = eeprom_read,
index e8b1e8d7abcbcccf632ccd67571de47866fb3f09..788aa7a1495c04c8a5087c1e989962d36e4f32e2 100644 (file)
@@ -402,6 +402,7 @@ static struct bin_attribute sysfs_fw_dump_attr = {
        .attr = {
                .name = "fw_dump",
                .mode = S_IRUSR | S_IWUSR,
+               .owner = THIS_MODULE,
        },
        .size = 0,
        .read = qla2x00_sysfs_read_fw_dump,
@@ -415,6 +416,7 @@ static struct bin_attribute sysfs_nvram_attr = {
        .attr = {
                .name = "nvram",
                .mode = S_IRUSR | S_IWUSR,
+               .owner = THIS_MODULE,
        },
        .size = sizeof(nvram_t),
        .read = qla2x00_sysfs_read_nvram,
index 04ae47ed6f5ee8794b82b77795288d0d1c56d3b4..6b4c28844f3f98cd2ef2f84a64706851aaba4710 100644 (file)
@@ -101,19 +101,27 @@ static int open(struct inode * inode, struct file * file)
        if (!kobj || !attr)
                goto Done;
 
+       /* Grab the module reference for this attribute if we have one */
+       error = -ENODEV;
+       if (!try_module_get(attr->attr.owner)) 
+               goto Done;
+
        error = -EACCES;
        if ((file->f_mode & FMODE_WRITE) && !attr->write)
-               goto Done;
+               goto Error;
        if ((file->f_mode & FMODE_READ) && !attr->read)
-               goto Done;
+               goto Error;
 
        error = -ENOMEM;
        file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
        if (!file->private_data)
-               goto Done;
+               goto Error;
 
        error = 0;
+    goto Done;
 
+ Error:
+       module_put(attr->attr.owner);
  Done:
        if (error && kobj)
                kobject_put(kobj);
@@ -123,10 +131,12 @@ static int open(struct inode * inode, struct file * file)
 static int release(struct inode * inode, struct file * file)
 {
        struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
+       struct bin_attribute * attr = file->f_dentry->d_fsdata;
        u8 * buffer = file->private_data;
 
        if (kobj) 
                kobject_put(kobj);
+       module_put(attr->attr.owner);
        kfree(buffer);
        return 0;
 }