aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2007-06-15 07:14:22 -0400
committerJens Axboe <jens.axboe@oracle.com>2007-06-15 07:14:22 -0400
commit00de00bdad278783b3664ad2969954a707f5944a (patch)
treed96e6dd310eb42e5f6c00dcc4ad8a22f6e0a92cd
parent17ee4f49ab2c802c7818fa71c4e7e351a7230b86 (diff)
splice: fix leak of pages on short splice to pipe
If the destination pipe is full and we already transferred data, we break out instead of waiting for more pipe room. The exit logic looks at spd->nr_pages to see if we moved everything inside the spd container, but we decrement that variable in the loop to decide when spd has emptied. Instead we want to compare to the original page count in the spd, so cache that in a local variable. Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r--fs/splice.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/fs/splice.c b/fs/splice.c
index 12d247f6ece5..186fad463c43 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -176,6 +176,7 @@ static const struct pipe_buf_operations user_page_pipe_buf_ops = {
176static ssize_t splice_to_pipe(struct pipe_inode_info *pipe, 176static 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;
@@ -254,7 +255,7 @@ static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
254 kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); 255 kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
255 } 256 }
256 257
257 while (page_nr < spd->nr_pages) 258 while (page_nr < spd_pages)
258 page_cache_release(spd->pages[page_nr++]); 259 page_cache_release(spd->pages[page_nr++]);
259 260
260 return ret; 261 return ret;