diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-15 16:15:01 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-15 16:15:01 -0700 |
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 = { static ssize_t splice_to_pipe(struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) { + unsigned int spd_pages = spd->nr_pages; int ret, do_wakeup, page_nr; ret = 0; @@ -244,17 +245,18 @@ static ssize_t splice_to_pipe(struct pipe_inode_info *pipe, pipe->waiting_writers--; } - if (pipe->inode) + if (pipe->inode) { mutex_unlock(&pipe->inode->i_mutex); - if (do_wakeup) { - smp_mb(); - if (waitqueue_active(&pipe->wait)) - wake_up_interruptible(&pipe->wait); - kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); + if (do_wakeup) { + smp_mb(); + if (waitqueue_active(&pipe->wait)) + wake_up_interruptible(&pipe->wait); + kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); + } } - while (page_nr < spd->nr_pages) + while (page_nr < spd_pages) page_cache_release(spd->pages[page_nr++]); return ret; @@ -811,7 +813,10 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); if (ret > 0) { + unsigned long nr_pages; + *ppos += ret; + nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; /* * 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, if (err) ret = err; } - balance_dirty_pages_ratelimited(mapping); + balance_dirty_pages_ratelimited_nr(mapping, nr_pages); } return ret; @@ -863,7 +868,10 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); if (ret > 0) { + unsigned long nr_pages; + *ppos += ret; + nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; /* * 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, if (err) ret = err; } - balance_dirty_pages_ratelimited(mapping); + balance_dirty_pages_ratelimited_nr(mapping, nr_pages); } return ret; |