aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/splice.c45
1 files changed, 30 insertions, 15 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 4f5e6b09fb26..27d6408ff490 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -720,22 +720,26 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
720 ssize_t ret; 720 ssize_t ret;
721 721
722 ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); 722 ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
723 723 if (ret > 0) {
724 /*
725 * If file or inode is SYNC and we actually wrote some data, sync it.
726 */
727 if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(mapping->host))
728 && ret > 0) {
729 struct inode *inode = mapping->host; 724 struct inode *inode = mapping->host;
730 int err;
731 725
732 mutex_lock(&inode->i_mutex); 726 *ppos += ret;
733 err = generic_osync_inode(mapping->host, mapping, 727
734 OSYNC_METADATA|OSYNC_DATA); 728 /*
735 mutex_unlock(&inode->i_mutex); 729 * If file or inode is SYNC and we actually wrote some data,
730 * sync it.
731 */
732 if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
733 int err;
734
735 mutex_lock(&inode->i_mutex);
736 err = generic_osync_inode(inode, mapping,
737 OSYNC_METADATA|OSYNC_DATA);
738 mutex_unlock(&inode->i_mutex);
736 739
737 if (err) 740 if (err)
738 ret = err; 741 ret = err;
742 }
739 } 743 }
740 744
741 return ret; 745 return ret;
@@ -937,6 +941,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
937{ 941{
938 struct pipe_inode_info *pipe; 942 struct pipe_inode_info *pipe;
939 loff_t offset, *off; 943 loff_t offset, *off;
944 long ret;
940 945
941 pipe = in->f_dentry->d_inode->i_pipe; 946 pipe = in->f_dentry->d_inode->i_pipe;
942 if (pipe) { 947 if (pipe) {
@@ -951,7 +956,12 @@ static long do_splice(struct file *in, loff_t __user *off_in,
951 } else 956 } else
952 off = &out->f_pos; 957 off = &out->f_pos;
953 958
954 return do_splice_from(pipe, out, off, len, flags); 959 ret = do_splice_from(pipe, out, off, len, flags);
960
961 if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
962 ret = -EFAULT;
963
964 return ret;
955 } 965 }
956 966
957 pipe = out->f_dentry->d_inode->i_pipe; 967 pipe = out->f_dentry->d_inode->i_pipe;
@@ -967,7 +977,12 @@ static long do_splice(struct file *in, loff_t __user *off_in,
967 } else 977 } else
968 off = &in->f_pos; 978 off = &in->f_pos;
969 979
970 return do_splice_to(in, off, pipe, len, flags); 980 ret = do_splice_to(in, off, pipe, len, flags);
981
982 if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
983 ret = -EFAULT;
984
985 return ret;
971 } 986 }
972 987
973 return -EINVAL; 988 return -EINVAL;