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

Commit e7848683 authored by Jan Kara's avatar Jan Kara Committed by Al Viro
Browse files

btrfs: Push mnt_want_write() outside of i_mutex



When mnt_want_write() starts to handle freezing it will get a full lock
semantics requiring proper lock ordering. So push mnt_want_write() call
consistently outside of i_mutex.

CC: Chris Mason <chris.mason@oracle.com>
CC: linux-btrfs@vger.kernel.org
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent e24f17da
Loading
Loading
Loading
Loading
+11 −12
Original line number Original line Diff line number Diff line
@@ -193,6 +193,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
	if (!inode_owner_or_capable(inode))
	if (!inode_owner_or_capable(inode))
		return -EACCES;
		return -EACCES;


	ret = mnt_want_write_file(file);
	if (ret)
		return ret;

	mutex_lock(&inode->i_mutex);
	mutex_lock(&inode->i_mutex);


	ip_oldflags = ip->flags;
	ip_oldflags = ip->flags;
@@ -207,10 +211,6 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
		}
		}
	}
	}


	ret = mnt_want_write_file(file);
	if (ret)
		goto out_unlock;

	if (flags & FS_SYNC_FL)
	if (flags & FS_SYNC_FL)
		ip->flags |= BTRFS_INODE_SYNC;
		ip->flags |= BTRFS_INODE_SYNC;
	else
	else
@@ -273,9 +273,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
		inode->i_flags = i_oldflags;
		inode->i_flags = i_oldflags;
	}
	}


	mnt_drop_write_file(file);
 out_unlock:
 out_unlock:
	mutex_unlock(&inode->i_mutex);
	mutex_unlock(&inode->i_mutex);
	mnt_drop_write_file(file);
	return ret;
	return ret;
}
}


@@ -641,6 +641,10 @@ static noinline int btrfs_mksubvol(struct path *parent,
	struct dentry *dentry;
	struct dentry *dentry;
	int error;
	int error;


	error = mnt_want_write(parent->mnt);
	if (error)
		return error;

	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);


	dentry = lookup_one_len(name, parent->dentry, namelen);
	dentry = lookup_one_len(name, parent->dentry, namelen);
@@ -652,13 +656,9 @@ static noinline int btrfs_mksubvol(struct path *parent,
	if (dentry->d_inode)
	if (dentry->d_inode)
		goto out_dput;
		goto out_dput;


	error = mnt_want_write(parent->mnt);
	if (error)
		goto out_dput;

	error = btrfs_may_create(dir, dentry);
	error = btrfs_may_create(dir, dentry);
	if (error)
	if (error)
		goto out_drop_write;
		goto out_dput;


	down_read(&BTRFS_I(dir)->root->fs_info->subvol_sem);
	down_read(&BTRFS_I(dir)->root->fs_info->subvol_sem);


@@ -676,12 +676,11 @@ static noinline int btrfs_mksubvol(struct path *parent,
		fsnotify_mkdir(dir, dentry);
		fsnotify_mkdir(dir, dentry);
out_up_read:
out_up_read:
	up_read(&BTRFS_I(dir)->root->fs_info->subvol_sem);
	up_read(&BTRFS_I(dir)->root->fs_info->subvol_sem);
out_drop_write:
	mnt_drop_write(parent->mnt);
out_dput:
out_dput:
	dput(dentry);
	dput(dentry);
out_unlock:
out_unlock:
	mutex_unlock(&dir->i_mutex);
	mutex_unlock(&dir->i_mutex);
	mnt_drop_write(parent->mnt);
	return error;
	return error;
}
}