summaryrefslogtreecommitdiffstats
path: root/drivers/base/core.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-11 15:24:56 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-11 15:24:56 -0800
commitf58df54a54451c5feb2fdc4bc2f4fb12cf79be01 (patch)
tree930b5892717ce84de93508407ebc35757bbc5ea0 /drivers/base/core.c
parent748e566b7e24541e05e3e70be311887a1262f2a1 (diff)
parent3589972e51fac1e02d0aaa576fa47f568cb94d40 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (27 commits) Driver core: fix race in dev_driver_string Driver Core: Early platform driver buffer sysfs: sysfs_setattr remove unnecessary permission check. sysfs: Factor out sysfs_rename from sysfs_rename_dir and sysfs_move_dir sysfs: Propagate renames to the vfs on demand sysfs: Gut sysfs_addrm_start and sysfs_addrm_finish sysfs: In sysfs_chmod_file lazily propagate the mode change. sysfs: Implement sysfs_getattr & sysfs_permission sysfs: Nicely indent sysfs_symlink_inode_operations sysfs: Update s_iattr on link and unlink. sysfs: Fix locking and factor out sysfs_sd_setattr sysfs: Simplify iattr time assignments sysfs: Simplify sysfs_chmod_file semantics sysfs: Use dentry_ops instead of directly playing with the dcache sysfs: Rename sysfs_d_iput to sysfs_dentry_iput sysfs: Update sysfs_setxattr so it updates secdata under the sysfs_mutex debugfs: fix create mutex racy fops and private data Driver core: Don't remove kobjects in device_shutdown. firmware_class: make request_firmware_nowait more useful Driver-Core: devtmpfs - set root directory mode to 0755 ...
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r--drivers/base/core.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 6bee6af8d8e..f1290cbd135 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -56,7 +56,14 @@ static inline int device_is_not_partition(struct device *dev)
*/
const char *dev_driver_string(const struct device *dev)
{
- return dev->driver ? dev->driver->name :
+ struct device_driver *drv;
+
+ /* dev->driver can change to NULL underneath us because of unbinding,
+ * so be careful about accessing it. dev->bus and dev->class should
+ * never change once they are set, so they don't need special care.
+ */
+ drv = ACCESS_ONCE(dev->driver);
+ return drv ? drv->name :
(dev->bus ? dev->bus->name :
(dev->class ? dev->class->name : ""));
}
@@ -987,6 +994,8 @@ done:
device_remove_class_symlinks(dev);
SymlinkError:
if (MAJOR(dev->devt))
+ devtmpfs_delete_node(dev);
+ if (MAJOR(dev->devt))
device_remove_sys_dev_entry(dev);
devtattrError:
if (MAJOR(dev->devt))
@@ -1728,8 +1737,5 @@ void device_shutdown(void)
dev->driver->shutdown(dev);
}
}
- kobject_put(sysfs_dev_char_kobj);
- kobject_put(sysfs_dev_block_kobj);
- kobject_put(dev_kobj);
async_synchronize_full();
}