aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-06-15 16:15:01 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-06-15 16:15:01 -0700
commite871e3c268a26c35ad805196a01d84a55bb755c6 (patch)
tree9189cae935058c46e158cb3a11342b6da9374b9f
parent3ea88d6738ebda95e05ada0c7b72f224d0a36953 (diff)
parent02676e5aee271c1f20d7d44249d26741aef1e846 (diff)
downloadlinux-2.6.34-ux500-e871e3c268a26c35ad805196a01d84a55bb755c6.tar.gz
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.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/fs/splice.c b/fs/splice.c
index cb211360273..e7d7080de2f 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;