Skip to content

Commit

Permalink
sysfs: Rewrite sysfs_drop_dentry.
Browse files Browse the repository at this point in the history
Currently we find the dentry to drop by looking at sd->s_dentry.
We can just as easily accomplish the same task by looking up the
sysfs inode and finding all of the dentries from there, with the
added bonus that we don't need to play with the sysfs_assoc_lock.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Tejun Heo <htejun@gmail.com>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Eric W. Biederman authored and Greg Kroah-Hartman committed Oct 12, 2007
1 parent 3efa65b commit 89bec09
Showing 1 changed file with 26 additions and 27 deletions.
53 changes: 26 additions & 27 deletions fs/sysfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,50 +565,49 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
* Drop dentry for @sd. @sd must have been unlinked from its
* parent on entry to this function such that it can't be looked
* up anymore.
*
* @sd->s_dentry which is protected with sysfs_assoc_lock points
* to the currently associated dentry but we're not holding a
* reference to it and racing with dput(). Grab dcache_lock and
* verify dentry before dropping it. If @sd->s_dentry is NULL or
* dput() beats us, no need to bother.
*/
static void sysfs_drop_dentry(struct sysfs_dirent *sd)
{
struct dentry *dentry = NULL;
struct inode *inode;
struct dentry *dentry;

inode = ilookup(sysfs_sb, sd->s_ino);
if (!inode)
return;

/* We're not holding a reference to ->s_dentry dentry but the
* field will stay valid as long as sysfs_assoc_lock is held.
/* Drop any existing dentries associated with sd.
*
* For the dentry to be properly freed we need to grab a
* reference to the dentry under the dcache lock, unhash it,
* and then put it. The playing with the dentry count allows
* dput to immediately free the dentry if it is not in use.
*/
spin_lock(&sysfs_assoc_lock);
repeat:
spin_lock(&dcache_lock);

/* drop dentry if it's there and dput() didn't kill it yet */
if (sd->s_dentry && sd->s_dentry->d_inode) {
dentry = dget_locked(sd->s_dentry);
list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
if (d_unhashed(dentry))
continue;
dget_locked(dentry);
spin_lock(&dentry->d_lock);
__d_drop(dentry);
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
dput(dentry);
goto repeat;
}

spin_unlock(&dcache_lock);
spin_unlock(&sysfs_assoc_lock);

dput(dentry);

/* adjust nlink and update timestamp */
inode = ilookup(sysfs_sb, sd->s_ino);
if (inode) {
mutex_lock(&inode->i_mutex);
mutex_lock(&inode->i_mutex);

inode->i_ctime = CURRENT_TIME;
inode->i_ctime = CURRENT_TIME;
drop_nlink(inode);
if (sysfs_type(sd) == SYSFS_DIR)
drop_nlink(inode);
if (sysfs_type(sd) == SYSFS_DIR)
drop_nlink(inode);

mutex_unlock(&inode->i_mutex);
iput(inode);
}
mutex_unlock(&inode->i_mutex);

iput(inode);
}

/**
Expand Down

0 comments on commit 89bec09

Please sign in to comment.