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: Jan Kara <jack@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
e24f17da35
commit
e7848683ae
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user