diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2009-04-14 13:48:38 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-04-15 06:10:11 -0400 |
commit | eb443e5a25d43996deb62b9bcee1a4ce5dea2ead (patch) | |
tree | 7f63bb98302137e249904d608d5bb4b919a987ed /fs/splice.c | |
parent | 2933970b960223076d6affcf7a77e2bc546b8102 (diff) |
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>
Diffstat (limited to 'fs/splice.c')
-rw-r--r-- | fs/splice.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/fs/splice.c b/fs/splice.c index 349576b2c75a..a1f595b9db40 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -895,17 +895,29 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
895 | }; | 895 | }; |
896 | ssize_t ret; | 896 | ssize_t ret; |
897 | 897 | ||
898 | WARN_ON(S_ISFIFO(inode->i_mode)); | 898 | if (pipe->inode) |
899 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT); | 899 | mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT); |
900 | ret = file_remove_suid(out); | 900 | |
901 | if (likely(!ret)) { | 901 | splice_from_pipe_begin(&sd); |
902 | if (pipe->inode) | 902 | do { |
903 | mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_CHILD); | 903 | ret = splice_from_pipe_next(pipe, &sd); |
904 | ret = __splice_from_pipe(pipe, &sd, pipe_to_file); | 904 | if (ret <= 0) |
905 | if (pipe->inode) | 905 | break; |
906 | mutex_unlock(&pipe->inode->i_mutex); | 906 | |
907 | } | 907 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD); |
908 | mutex_unlock(&inode->i_mutex); | 908 | ret = file_remove_suid(out); |
909 | if (!ret) | ||
910 | ret = splice_from_pipe_feed(pipe, &sd, pipe_to_file); | ||
911 | mutex_unlock(&inode->i_mutex); | ||
912 | } while (ret > 0); | ||
913 | splice_from_pipe_end(pipe, &sd); | ||
914 | |||
915 | if (pipe->inode) | ||
916 | mutex_unlock(&pipe->inode->i_mutex); | ||
917 | |||
918 | if (sd.num_spliced) | ||
919 | ret = sd.num_spliced; | ||
920 | |||
909 | if (ret > 0) { | 921 | if (ret > 0) { |
910 | unsigned long nr_pages; | 922 | unsigned long nr_pages; |
911 | 923 | ||