Sfoglia il codice sorgente

[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>
Greg Kroah-Hartman 19 anni fa
parent
commit
641e6f30a0
2 ha cambiato i file con 6 aggiunte e 1 eliminazioni
  1. 1 0
      fs/sysfs/dir.c
  2. 5 1
      fs/sysfs/inode.c

+ 1 - 0
fs/sysfs/dir.c

@@ -302,6 +302,7 @@ void sysfs_remove_dir(struct kobject * kobj)
 	 * Drop reference from dget() on entrance.
 	 * Drop reference from dget() on entrance.
 	 */
 	 */
 	dput(dentry);
 	dput(dentry);
+	kobj->dentry = NULL;
 }
 }
 
 
 int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
 int sysfs_rename_dir(struct kobject * kobj, const char *new_name)

+ 5 - 1
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)
 void sysfs_hash_and_remove(struct dentry * dir, const char * name)
 {
 {
 	struct sysfs_dirent * sd;
 	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)
 	if (dir->d_inode == NULL)
 		/* no inode means this hasn't been made visible yet */
 		/* no inode means this hasn't been made visible yet */
 		return;
 		return;
 
 
+	parent_sd = dir->d_fsdata;
 	mutex_lock(&dir->d_inode->i_mutex);
 	mutex_lock(&dir->d_inode->i_mutex);
 	list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
 	list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
 		if (!sd->s_element)
 		if (!sd->s_element)