diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-15 19:15:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-15 19:15:01 -0400 |
commit | e871e3c268a26c35ad805196a01d84a55bb755c6 (patch) | |
tree | 9189cae935058c46e158cb3a11342b6da9374b9f | |
parent | 3ea88d6738ebda95e05ada0c7b72f224d0a36953 (diff) | |
parent | 02676e5aee271c1f20d7d44249d26741aef1e846 (diff) |
Merge branch 'splice-2.6.22' of git://git.kernel.dk/data/git/linux-2.6-block
* 'splice-2.6.22' of git://git.kernel.dk/data/git/linux-2.6-block:
splice: only check do_wakeup in splice_to_pipe() for a real pipe
splice: fix leak of pages on short splice to pipe
splice: adjust balance_dirty_pages_ratelimited() call
-rw-r--r-- | fs/splice.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/fs/splice.c b/fs/splice.c index cb211360273a..e7d7080de2f9 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -176,6 +176,7 @@ static const struct pipe_buf_operations user_page_pipe_buf_ops = { | |||
176 | static ssize_t splice_to_pipe(struct pipe_inode_info *pipe, | 176 | static ssize_t splice_to_pipe(struct pipe_inode_info *pipe, |
177 | struct splice_pipe_desc *spd) | 177 | struct splice_pipe_desc *spd) |
178 | { | 178 | { |
179 | unsigned int spd_pages = spd->nr_pages; | ||
179 | int ret, do_wakeup, page_nr; | 180 | int ret, do_wakeup, page_nr; |
180 | 181 | ||
181 | ret = 0; | 182 | ret = 0; |
@@ -244,17 +245,18 @@ static ssize_t splice_to_pipe(struct pipe_inode_info *pipe, | |||
244 | pipe->waiting_writers--; | 245 | pipe->waiting_writers--; |
245 | } | 246 | } |
246 | 247 | ||
247 | if (pipe->inode) | 248 | if (pipe->inode) { |
248 | mutex_unlock(&pipe->inode->i_mutex); | 249 | mutex_unlock(&pipe->inode->i_mutex); |
249 | 250 | ||
250 | if (do_wakeup) { | 251 | if (do_wakeup) { |
251 | smp_mb(); | 252 | smp_mb(); |
252 | if (waitqueue_active(&pipe->wait)) | 253 | if (waitqueue_active(&pipe->wait)) |
253 | wake_up_interruptible(&pipe->wait); | 254 | wake_up_interruptible(&pipe->wait); |
254 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); | 255 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); |
256 | } | ||
255 | } | 257 | } |
256 | 258 | ||
257 | while (page_nr < spd->nr_pages) | 259 | while (page_nr < spd_pages) |
258 | page_cache_release(spd->pages[page_nr++]); | 260 | page_cache_release(spd->pages[page_nr++]); |
259 | 261 | ||
260 | return ret; | 262 | return ret; |
@@ -811,7 +813,10 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, | |||
811 | 813 | ||
812 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); | 814 | ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); |
813 | if (ret > 0) { | 815 | if (ret > 0) { |
816 | unsigned long nr_pages; | ||
817 | |||
814 | *ppos += ret; | 818 | *ppos += ret; |
819 | nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
815 | 820 | ||
816 | /* | 821 | /* |
817 | * If file or inode is SYNC and we actually wrote some data, | 822 | * If file or inode is SYNC and we actually wrote some data, |
@@ -824,7 +829,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, | |||
824 | if (err) | 829 | if (err) |
825 | ret = err; | 830 | ret = err; |
826 | } | 831 | } |
827 | balance_dirty_pages_ratelimited(mapping); | 832 | balance_dirty_pages_ratelimited_nr(mapping, nr_pages); |
828 | } | 833 | } |
829 | 834 | ||
830 | return ret; | 835 | return ret; |
@@ -863,7 +868,10 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
863 | 868 | ||
864 | ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); | 869 | ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); |
865 | if (ret > 0) { | 870 | if (ret > 0) { |
871 | unsigned long nr_pages; | ||
872 | |||
866 | *ppos += ret; | 873 | *ppos += ret; |
874 | nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
867 | 875 | ||
868 | /* | 876 | /* |
869 | * If file or inode is SYNC and we actually wrote some data, | 877 | * If file or inode is SYNC and we actually wrote some data, |
@@ -878,7 +886,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, | |||
878 | if (err) | 886 | if (err) |
879 | ret = err; | 887 | ret = err; |
880 | } | 888 | } |
881 | balance_dirty_pages_ratelimited(mapping); | 889 | balance_dirty_pages_ratelimited_nr(mapping, nr_pages); |
882 | } | 890 | } |
883 | 891 | ||
884 | return ret; | 892 | return ret; |