Commit 1cdccc69 authored by Patrick Mochel's avatar Patrick Mochel

sysfs: fix up directory removal, once and for all.

This patch was previously integrated, but dropped erroneously by a bk 
merge. 

This fixes file cleanup during a sysfs directory removal by deleting files
from ->d_subdirs as they're iterated over, then checking if we can get a
reference on them.
parent 1d4a1554
......@@ -71,7 +71,7 @@ int sysfs_create_dir(struct kobject * kobj)
void sysfs_remove_dir(struct kobject * kobj)
{
struct list_head * node, * next;
struct list_head * node;
struct dentry * dentry = dget(kobj->dentry);
struct dentry * parent;
......@@ -83,31 +83,28 @@ void sysfs_remove_dir(struct kobject * kobj)
down(&parent->d_inode->i_sem);
down(&dentry->d_inode->i_sem);
list_for_each_safe(node,next,&dentry->d_subdirs) {
struct dentry * d = dget(list_entry(node,struct dentry,d_child));
/**
* Make sure dentry is still there
*/
pr_debug(" o %s: ",d->d_name.name);
if (d->d_inode) {
spin_lock(&dcache_lock);
node = dentry->d_subdirs.next;
while (node != &dentry->d_subdirs) {
struct dentry * d = list_entry(node,struct dentry,d_child);
list_del_init(node);
pr_debug(" o %s (%d): ",d->d_name.name,atomic_read(&d->d_count));
if (d->d_inode) {
d = dget_locked(d);
pr_debug("removing");
/**
* Unlink and unhash.
*/
simple_unlink(dentry->d_inode,d);
spin_unlock(&dcache_lock);
d_delete(d);
/**
* Drop reference from initial sysfs_get_dentry().
*/
simple_unlink(dentry->d_inode,d);
dput(d);
spin_lock(&dcache_lock);
}
pr_debug(" done (%d)\n",atomic_read(&d->d_count));
/**
* drop reference from dget() above.
*/
dput(d);
pr_debug(" done\n");
node = dentry->d_subdirs.next;
}
up(&dentry->d_inode->i_sem);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment