summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-03-16 15:44:26 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2006-03-20 13:42:57 -0800
commit641e6f30a095f3752ed84fd9d279382f5d3ef4c1 (patch)
tree59b57c14f9249488ded6814de4512f7f9949289f
parentc4a1745aa09fc110afdefea0e5d025043e348bae (diff)
downloadlinux-3.10-641e6f30a095f3752ed84fd9d279382f5d3ef4c1.tar.gz
linux-3.10-641e6f30a095f3752ed84fd9d279382f5d3ef4c1.tar.bz2
linux-3.10-641e6f30a095f3752ed84fd9d279382f5d3ef4c1.zip
[PATCH] sysfs: sysfs_remove_dir() needs to invalidate the dentry
When calling sysfs_remove_dir() don't allow any further sysfs functions to work for this kobject anymore. This fixes a nasty USB cdc-acm oops on disconnect. Many thanks to Bob Copeland and Paul Fulghum for taking the time to track this down. Cc: Bob Copeland <email@bobcopeland.com> Cc: Paul Fulghum <paulkf@microgate.com> Cc: Maneesh Soni <maneesh@in.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--fs/sysfs/dir.c1
-rw-r--r--fs/sysfs/inode.c6
2 files changed, 6 insertions, 1 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 49bd219275d..cfd290d3d6b 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -302,6 +302,7 @@ void sysfs_remove_dir(struct kobject * kobj)
* Drop reference from dget() on entrance.
*/
dput(dentry);
+ kobj->dentry = NULL;
}
int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 689f7bcfaf3..6beee6f6a67 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -227,12 +227,16 @@ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
void sysfs_hash_and_remove(struct dentry * dir, const char * name)
{
struct sysfs_dirent * sd;
- struct sysfs_dirent * parent_sd = dir->d_fsdata;
+ struct sysfs_dirent * parent_sd;
+
+ if (!dir)
+ return;
if (dir->d_inode == NULL)
/* no inode means this hasn't been made visible yet */
return;
+ parent_sd = dir->d_fsdata;
mutex_lock(&dir->d_inode->i_mutex);
list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
if (!sd->s_element)