mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
splice: fix i_mutex locking in generic_splice_write()
Rearrange locking of i_mutex on destination so it's only held while buffers are copied with the pipe_to_file() actor, and not while waiting for more data on the pipe. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
This commit is contained in:
parent
2933970b96
commit
eb443e5a25
34
fs/splice.c
34
fs/splice.c
@ -895,17 +895,29 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
|
|||||||
};
|
};
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
WARN_ON(S_ISFIFO(inode->i_mode));
|
if (pipe->inode)
|
||||||
mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
|
mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT);
|
||||||
ret = file_remove_suid(out);
|
|
||||||
if (likely(!ret)) {
|
splice_from_pipe_begin(&sd);
|
||||||
if (pipe->inode)
|
do {
|
||||||
mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD);
|
ret = splice_from_pipe_next(pipe, &sd);
|
||||||
ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
|
if (ret <= 0)
|
||||||
if (pipe->inode)
|
break;
|
||||||
mutex_unlock(&pipe->inode->i_mutex);
|
|
||||||
}
|
mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
|
||||||
mutex_unlock(&inode->i_mutex);
|
ret = file_remove_suid(out);
|
||||||
|
if (!ret)
|
||||||
|
ret = splice_from_pipe_feed(pipe, &sd, pipe_to_file);
|
||||||
|
mutex_unlock(&inode->i_mutex);
|
||||||
|
} while (ret > 0);
|
||||||
|
splice_from_pipe_end(pipe, &sd);
|
||||||
|
|
||||||
|
if (pipe->inode)
|
||||||
|
mutex_unlock(&pipe->inode->i_mutex);
|
||||||
|
|
||||||
|
if (sd.num_spliced)
|
||||||
|
ret = sd.num_spliced;
|
||||||
|
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
unsigned long nr_pages;
|
unsigned long nr_pages;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user