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

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
...@@ -193,6 +193,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment