--- ../tmp/linux-2.6.0-test5/lib/kobject.c 2003-09-09 23:46:26.000000000 +0400 +++ linux-2.6.0-test5/lib/kobject.c 2003-09-14 12:24:20.000000000 +0400 @@ -236,8 +236,6 @@ static void unlink(struct kobject * kobj list_del_init(&kobj->entry); up_write(&kobj->kset->subsys->rwsem); } - if (kobj->parent) - kobject_put(kobj->parent); kobject_put(kobj); } @@ -448,6 +446,8 @@ void kobject_cleanup(struct kobject * ko if (kobj->k_name != kobj->name) kfree(kobj->k_name); kobj->k_name = NULL; + if (kobj->parent) + kobject_put(kobj->parent); if (t && t->release) t->release(kobj); if (s) --- ../tmp/linux-2.6.0-test5/fs/sysfs/dir.c 2003-09-09 23:46:13.000000000 +0400 +++ linux-2.6.0-test5/fs/sysfs/dir.c 2003-09-14 12:25:20.000000000 +0400 @@ -84,8 +84,16 @@ static void remove_dir(struct dentry * d { struct dentry * parent = dget(d->d_parent); down(&parent->d_inode->i_sem); - d_delete(d); - simple_rmdir(parent->d_inode,d); + /* + * It is possible that parent has already been removed, in which + * case directory is already unhashed and dput. + * Note that this won't update parent->d_inode->i_nlink; OTOH + * parent should already be dead + */ + if (!d_unhashed(d)) { + d_delete(d); + simple_rmdir(parent->d_inode,d); + } pr_debug(" o %s removing done (%d)\n",d->d_name.name, atomic_read(&d->d_count));