diff options
| -rw-r--r-- | fs/splice.c | 80 | ||||
| -rw-r--r-- | include/linux/fs.h | 2 |
2 files changed, 68 insertions, 14 deletions
diff --git a/fs/splice.c b/fs/splice.c index c1072b6940c3..68e20e65c6e1 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -707,13 +707,12 @@ out_ret: | |||
| 707 | * key here is the 'actor' worker passed in that actually moves the data | 707 | * key here is the 'actor' worker passed in that actually moves the data |
| 708 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. | 708 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. |
| 709 | */ | 709 | */ |
| 710 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | 710 | static ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, |
| 711 | loff_t *ppos, size_t len, unsigned int flags, | 711 | struct file *out, loff_t *ppos, size_t len, |
| 712 | splice_actor *actor) | 712 | unsigned int flags, splice_actor *actor) |
| 713 | { | 713 | { |
| 714 | int ret, do_wakeup, err; | 714 | int ret, do_wakeup, err; |
| 715 | struct splice_desc sd; | 715 | struct splice_desc sd; |
| 716 | struct inode *inode = out->f_mapping->host; | ||
| 717 | 716 | ||
| 718 | ret = 0; | 717 | ret = 0; |
| 719 | do_wakeup = 0; | 718 | do_wakeup = 0; |
| @@ -723,14 +722,6 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
| 723 | sd.file = out; | 722 | sd.file = out; |
| 724 | sd.pos = *ppos; | 723 | sd.pos = *ppos; |
| 725 | 724 | ||
| 726 | /* | ||
| 727 | * The actor worker might be calling ->prepare_write and | ||
| 728 | * ->commit_write. Most of the time, these expect i_mutex to | ||
| 729 | * be held. Since this may result in an ABBA deadlock with | ||
| 730 | * pipe->inode, we have to order lock acquiry here. | ||
| 731 | */ | ||
| 732 | inode_double_lock(inode, pipe->inode); | ||
| 733 | |||
| 734 | for (;;) { | 725 | for (;;) { |
| 735 | if (pipe->nrbufs) { | 726 | if (pipe->nrbufs) { |
| 736 | struct pipe_buffer *buf = pipe->bufs + pipe->curbuf; | 727 | struct pipe_buffer *buf = pipe->bufs + pipe->curbuf; |
| @@ -803,8 +794,6 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
| 803 | pipe_wait(pipe); | 794 | pipe_wait(pipe); |
| 804 | } | 795 | } |
| 805 | 796 | ||
| 806 | inode_double_unlock(inode, pipe->inode); | ||
| 807 | |||
| 808 | if (do_wakeup) { | 797 | if (do_wakeup) { |
| 809 | smp_mb(); | 798 | smp_mb(); |
| 810 | if (waitqueue_active(&pipe->wait)) | 799 | if (waitqueue_active(&pipe->wait)) |
| @@ -815,6 +804,69 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
| 815 | return ret; | 804 | return ret; |
| 816 | } | 805 | } |
| 817 | 806 | ||
| 807 | ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | ||
| 808 | loff_t *ppos, size_t len, unsigned int flags, | ||
| 809 | splice_actor *actor) | ||
| 810 | { | ||
| 811 | ssize_t ret; | ||
| 812 | struct inode *inode = out->f_mapping->host; | ||
| 813 | |||
| 814 | /* | ||
| 815 | * The actor worker might be calling ->prepare_write and | ||
| 816 | * ->commit_write. Most of the time, these expect i_mutex to | ||
| 817 | * be held. Since this may result in an ABBA deadlock with | ||
| 818 | * pipe->inode, we have to order lock acquiry here. | ||
| 819 | */ | ||
| 820 | inode_double_lock(inode, pipe->inode); | ||
| 821 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, actor); | ||
| 822 | inode_double_unlock(inode, pipe->inode); | ||
| 823 | |||
| 824 | return ret; | ||
| 825 | } | ||
| 826 | |||
| 827 | /** | ||
| 828 | * generic_file_splice_write_nolock - generic_file_splice_write without mutexes | ||
| 829 | * @pipe: pipe info | ||
| 830 | * @out: file to write to | ||
| 831 | * @len: number of bytes to splice | ||
| 832 | * @flags: splice modifier flags | ||
| 833 | * | ||
| 834 | * Will either move or copy pages (determined by @flags options) from | ||
| 835 | * the given pipe inode to the given file. The caller is responsible | ||
| 836 | * for acquiring i_mutex on both inodes. | ||
| 837 | * | ||
| 838 | */ | ||
| 839 | ssize_t | ||
| 840 | generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, | ||
| 841 | loff_t *ppos, size_t len, unsigned int flags) | ||
| 842 | { | ||
| 843 | struct address_space *mapping = out->f_mapping; | ||
| 844 | struct inode *inode = mapping->host; | ||
| 845 | ssize_t ret; | ||
| 846 | int err; | ||
| 847 | |||
| 848 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); | ||
| 849 | if (ret > 0) { | ||
| 850 | *ppos += ret; | ||
| 851 | |||
| 852 | /* | ||
| 853 | * If file or inode is SYNC and we actually wrote some data, | ||
| 854 | * sync it. | ||
| 855 | */ | ||
| 856 | if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) { | ||
| 857 | err = generic_osync_inode(inode, mapping, | ||
| 858 | OSYNC_METADATA|OSYNC_DATA); | ||
| 859 | |||
| 860 | if (err) | ||
| 861 | ret = err; | ||
| 862 | } | ||
| 863 | } | ||
| 864 | |||
| 865 | return ret; | ||
| 866 | } | ||
| 867 | |||
| 868 | EXPORT_SYMBOL(generic_file_splice_write_nolock); | ||
| 869 | |||
| 818 | /** | 870 | /** |
| 819 | * generic_file_splice_write - splice data from a pipe to a file | 871 | * generic_file_splice_write - splice data from a pipe to a file |
| 820 | * @pipe: pipe info | 872 | * @pipe: pipe info |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 853a02f23936..d695ba2346a3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -1758,6 +1758,8 @@ extern ssize_t generic_file_splice_read(struct file *, loff_t *, | |||
| 1758 | struct pipe_inode_info *, size_t, unsigned int); | 1758 | struct pipe_inode_info *, size_t, unsigned int); |
| 1759 | extern ssize_t generic_file_splice_write(struct pipe_inode_info *, | 1759 | extern ssize_t generic_file_splice_write(struct pipe_inode_info *, |
| 1760 | struct file *, loff_t *, size_t, unsigned int); | 1760 | struct file *, loff_t *, size_t, unsigned int); |
| 1761 | extern ssize_t generic_file_splice_write_nolock(struct pipe_inode_info *, | ||
| 1762 | struct file *, loff_t *, size_t, unsigned int); | ||
| 1761 | extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, | 1763 | extern ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, |
| 1762 | struct file *out, loff_t *, size_t len, unsigned int flags); | 1764 | struct file *out, loff_t *, size_t len, unsigned int flags); |
| 1763 | extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | 1765 | extern long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, |
