Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0bcb568 authored by Tejun Heo's avatar Tejun Heo Committed by Greg Kroah-Hartman
Browse files

sysfs: make sysfs_drop_dentry() access inodes using ilookup()



sysfs_drop_dentry() used to go through sd->s_dentry and
sd->s_parent->s_dentry to access the inodes.  This is incorrect
because inode can be cached without dentry.

This patch makes sysfs_drop_dentry() access inodes using ilookup() on
sd->s_ino.  This is both correct and simpler.

Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 9d9307da
Loading
Loading
Loading
Loading
+28 −35
Original line number Original line Diff line number Diff line
@@ -219,9 +219,9 @@ void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
 */
 */
void sysfs_drop_dentry(struct sysfs_dirent *sd)
void sysfs_drop_dentry(struct sysfs_dirent *sd)
{
{
	struct dentry *dentry = NULL, *parent = NULL;
	struct dentry *dentry = NULL;
	struct inode *dir;
	struct timespec curtime;
	struct timespec curtime;
	struct inode *inode;


	/* We're not holding a reference to ->s_dentry dentry but the
	/* We're not holding a reference to ->s_dentry dentry but the
	 * field will stay valid as long as sysfs_lock is held.
	 * field will stay valid as long as sysfs_lock is held.
@@ -229,19 +229,9 @@ void sysfs_drop_dentry(struct sysfs_dirent *sd)
	spin_lock(&sysfs_lock);
	spin_lock(&sysfs_lock);
	spin_lock(&dcache_lock);
	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) {
	if (sd->s_dentry && sd->s_dentry->d_inode) {
		/* get dentry if it's there and dput() didn't kill it yet */
		dentry = dget_locked(sd->s_dentry);
		dentry = dget_locked(sd->s_dentry);
		parent = dentry->d_parent;
	} else if (sd->s_parent->s_dentry->d_inode) {
		/* We need to update the parent even if dentry for the
		 * victim itself doesn't exist.
		 */
		parent = dget_locked(sd->s_parent->s_dentry);
	}

	/* drop */
	if (dentry) {
		spin_lock(&dentry->d_lock);
		spin_lock(&dentry->d_lock);
		__d_drop(dentry);
		__d_drop(dentry);
		spin_unlock(&dentry->d_lock);
		spin_unlock(&dentry->d_lock);
@@ -250,36 +240,39 @@ void sysfs_drop_dentry(struct sysfs_dirent *sd)
	spin_unlock(&dcache_lock);
	spin_unlock(&dcache_lock);
	spin_unlock(&sysfs_lock);
	spin_unlock(&sysfs_lock);


	/* nothing to do if the parent isn't in dcache */
	dput(dentry);
	if (!parent)
	/* XXX: unpin if directory, this will go away soon */
		return;
	if (sd->s_type & SYSFS_DIR)
		dput(dentry);


	/* adjust nlink and update timestamp */
	/* adjust nlink and update timestamp */
	dir = parent->d_inode;
	mutex_lock(&dir->i_mutex);

	curtime = CURRENT_TIME;
	curtime = CURRENT_TIME;


	dir->i_ctime = dir->i_mtime = curtime;
	inode = ilookup(sysfs_sb, sd->s_ino);
	if (inode) {
		mutex_lock(&inode->i_mutex);


	if (dentry) {
		inode->i_ctime = curtime;
		dentry->d_inode->i_ctime = curtime;
		drop_nlink(inode);
		drop_nlink(dentry->d_inode);
		if (sd->s_type & SYSFS_DIR)
		if (sd->s_type & SYSFS_DIR) {
			drop_nlink(inode);
			drop_nlink(dentry->d_inode);

			drop_nlink(dir);
		mutex_unlock(&inode->i_mutex);
			/* XXX: unpin if directory, this will go away soon */
		iput(inode);
			dput(dentry);
		}
	}
	}


	mutex_unlock(&dir->i_mutex);
	/* adjust nlink and udpate timestamp of the parent */
	inode = ilookup(sysfs_sb, sd->s_parent->s_ino);
	if (inode) {
		mutex_lock(&inode->i_mutex);


	/* bye bye */
		inode->i_ctime = inode->i_mtime = curtime;
	if (dentry)
		if (sd->s_type & SYSFS_DIR)
		dput(dentry);
			drop_nlink(inode);
	else

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


int sysfs_hash_and_remove(struct dentry * dir, const char * name)
int sysfs_hash_and_remove(struct dentry * dir, const char * name)