diff options
author | Tejun Heo <htejun@gmail.com> | 2007-06-13 14:45:16 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-11 19:09:06 -0400 |
commit | dbde0fcf9f8f6d477af3c32d9979e789ee680cde (patch) | |
tree | 12a1240213d59c061fec60325c7d5ebb1edebcd7 /fs/sysfs/dir.c | |
parent | 198a2a847015805c6f57d8cc732bdaaccb494007 (diff) |
sysfs: reimplement sysfs_drop_dentry()
This patch reimplements sysfs_drop_dentry() such that remove_dir() can
use it to drop dentry instead of using a separate mechanism. With
this change, making directories reclaimable is much easier.
This patch used to contain fixes for two race conditions around
sd->s_dentry but that part has been separated out and included into
mainline early as commit 6aa054aadfea613a437ad0b15d38eca2b963fc0a and
dd14cbc994709a1c5a64ed3621f583c49a27e521.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r-- | fs/sysfs/dir.c | 18 |
1 files changed, 5 insertions, 13 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 01eeb4b954b1..bc11a263aa53 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -372,22 +372,19 @@ const struct inode_operations sysfs_dir_inode_operations = { | |||
372 | 372 | ||
373 | static void remove_dir(struct dentry * d) | 373 | static void remove_dir(struct dentry * d) |
374 | { | 374 | { |
375 | struct dentry * parent = dget(d->d_parent); | 375 | struct dentry *parent = d->d_parent; |
376 | struct sysfs_dirent * sd; | 376 | struct sysfs_dirent *sd = d->d_fsdata; |
377 | 377 | ||
378 | mutex_lock(&parent->d_inode->i_mutex); | 378 | mutex_lock(&parent->d_inode->i_mutex); |
379 | d_delete(d); | 379 | |
380 | sd = d->d_fsdata; | ||
381 | list_del_init(&sd->s_sibling); | 380 | list_del_init(&sd->s_sibling); |
382 | if (d->d_inode) | ||
383 | simple_rmdir(parent->d_inode,d); | ||
384 | 381 | ||
385 | pr_debug(" o %s removing done (%d)\n",d->d_name.name, | 382 | pr_debug(" o %s removing done (%d)\n",d->d_name.name, |
386 | atomic_read(&d->d_count)); | 383 | atomic_read(&d->d_count)); |
387 | 384 | ||
388 | mutex_unlock(&parent->d_inode->i_mutex); | 385 | mutex_unlock(&parent->d_inode->i_mutex); |
389 | dput(parent); | ||
390 | 386 | ||
387 | sysfs_drop_dentry(sd); | ||
391 | sysfs_deactivate(sd); | 388 | sysfs_deactivate(sd); |
392 | sysfs_put(sd); | 389 | sysfs_put(sd); |
393 | } | 390 | } |
@@ -404,7 +401,6 @@ static void __sysfs_remove_dir(struct dentry *dentry) | |||
404 | struct sysfs_dirent * parent_sd; | 401 | struct sysfs_dirent * parent_sd; |
405 | struct sysfs_dirent * sd, * tmp; | 402 | struct sysfs_dirent * sd, * tmp; |
406 | 403 | ||
407 | dget(dentry); | ||
408 | if (!dentry) | 404 | if (!dentry) |
409 | return; | 405 | return; |
410 | 406 | ||
@@ -415,21 +411,17 @@ static void __sysfs_remove_dir(struct dentry *dentry) | |||
415 | if (!sd->s_type || !(sd->s_type & SYSFS_NOT_PINNED)) | 411 | if (!sd->s_type || !(sd->s_type & SYSFS_NOT_PINNED)) |
416 | continue; | 412 | continue; |
417 | list_move(&sd->s_sibling, &removed); | 413 | list_move(&sd->s_sibling, &removed); |
418 | sysfs_drop_dentry(sd, dentry); | ||
419 | } | 414 | } |
420 | mutex_unlock(&dentry->d_inode->i_mutex); | 415 | mutex_unlock(&dentry->d_inode->i_mutex); |
421 | 416 | ||
422 | list_for_each_entry_safe(sd, tmp, &removed, s_sibling) { | 417 | list_for_each_entry_safe(sd, tmp, &removed, s_sibling) { |
423 | list_del_init(&sd->s_sibling); | 418 | list_del_init(&sd->s_sibling); |
419 | sysfs_drop_dentry(sd); | ||
424 | sysfs_deactivate(sd); | 420 | sysfs_deactivate(sd); |
425 | sysfs_put(sd); | 421 | sysfs_put(sd); |
426 | } | 422 | } |
427 | 423 | ||
428 | remove_dir(dentry); | 424 | remove_dir(dentry); |
429 | /** | ||
430 | * Drop reference from dget() on entrance. | ||
431 | */ | ||
432 | dput(dentry); | ||
433 | } | 425 | } |
434 | 426 | ||
435 | /** | 427 | /** |