aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r--fs/sysfs/dir.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index edb30621b82f..c6f3b697064c 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -435,6 +435,62 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
435} 435}
436 436
437/** 437/**
438 * sysfs_drop_dentry - drop dentry for the specified sysfs_dirent
439 * @sd: target sysfs_dirent
440 *
441 * Drop dentry for @sd. @sd must have been unlinked from its
442 * parent on entry to this function such that it can't be looked
443 * up anymore.
444 *
445 * @sd->s_dentry which is protected with sysfs_assoc_lock points
446 * to the currently associated dentry but we're not holding a
447 * reference to it and racing with dput(). Grab dcache_lock and
448 * verify dentry before dropping it. If @sd->s_dentry is NULL or
449 * dput() beats us, no need to bother.
450 */
451static void sysfs_drop_dentry(struct sysfs_dirent *sd)
452{
453 struct dentry *dentry = NULL;
454 struct inode *inode;
455
456 /* We're not holding a reference to ->s_dentry dentry but the
457 * field will stay valid as long as sysfs_assoc_lock is held.
458 */
459 spin_lock(&sysfs_assoc_lock);
460 spin_lock(&dcache_lock);
461
462 /* drop dentry if it's there and dput() didn't kill it yet */
463 if (sd->s_dentry && sd->s_dentry->d_inode) {
464 dentry = dget_locked(sd->s_dentry);
465 spin_lock(&dentry->d_lock);
466 __d_drop(dentry);
467 spin_unlock(&dentry->d_lock);
468 }
469
470 spin_unlock(&dcache_lock);
471 spin_unlock(&sysfs_assoc_lock);
472
473 dput(dentry);
474 /* XXX: unpin if directory, this will go away soon */
475 if (sysfs_type(sd) == SYSFS_DIR)
476 dput(dentry);
477
478 /* adjust nlink and update timestamp */
479 inode = ilookup(sysfs_sb, sd->s_ino);
480 if (inode) {
481 mutex_lock(&inode->i_mutex);
482
483 inode->i_ctime = CURRENT_TIME;
484 drop_nlink(inode);
485 if (sysfs_type(sd) == SYSFS_DIR)
486 drop_nlink(inode);
487
488 mutex_unlock(&inode->i_mutex);
489 iput(inode);
490 }
491}
492
493/**
438 * sysfs_addrm_finish - finish up sysfs_dirent add/remove 494 * sysfs_addrm_finish - finish up sysfs_dirent add/remove
439 * @acxt: addrm context to finish up 495 * @acxt: addrm context to finish up
440 * 496 *