aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/fs/splice.c b/fs/splice.c
index c9f1318a3b82..7bf08fa22ec9 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -273,13 +273,16 @@ void spd_release_page(struct splice_pipe_desc *spd, unsigned int i)
273 * Check if we need to grow the arrays holding pages and partial page 273 * Check if we need to grow the arrays holding pages and partial page
274 * descriptions. 274 * descriptions.
275 */ 275 */
276int splice_grow_spd(struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) 276int splice_grow_spd(const struct pipe_inode_info *pipe, struct splice_pipe_desc *spd)
277{ 277{
278 if (pipe->buffers <= PIPE_DEF_BUFFERS) 278 unsigned int buffers = ACCESS_ONCE(pipe->buffers);
279
280 spd->nr_pages_max = buffers;
281 if (buffers <= PIPE_DEF_BUFFERS)
279 return 0; 282 return 0;
280 283
281 spd->pages = kmalloc(pipe->buffers * sizeof(struct page *), GFP_KERNEL); 284 spd->pages = kmalloc(buffers * sizeof(struct page *), GFP_KERNEL);
282 spd->partial = kmalloc(pipe->buffers * sizeof(struct partial_page), GFP_KERNEL); 285 spd->partial = kmalloc(buffers * sizeof(struct partial_page), GFP_KERNEL);
283 286
284 if (spd->pages && spd->partial) 287 if (spd->pages && spd->partial)
285 return 0; 288 return 0;
@@ -289,10 +292,9 @@ int splice_grow_spd(struct pipe_inode_info *pipe, struct splice_pipe_desc *spd)
289 return -ENOMEM; 292 return -ENOMEM;
290} 293}
291 294
292void splice_shrink_spd(struct pipe_inode_info *pipe, 295void splice_shrink_spd(struct splice_pipe_desc *spd)
293 struct splice_pipe_desc *spd)
294{ 296{
295 if (pipe->buffers <= PIPE_DEF_BUFFERS) 297 if (spd->nr_pages_max <= PIPE_DEF_BUFFERS)
296 return; 298 return;
297 299
298 kfree(spd->pages); 300 kfree(spd->pages);
@@ -315,6 +317,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
315 struct splice_pipe_desc spd = { 317 struct splice_pipe_desc spd = {
316 .pages = pages, 318 .pages = pages,
317 .partial = partial, 319 .partial = partial,
320 .nr_pages_max = PIPE_DEF_BUFFERS,
318 .flags = flags, 321 .flags = flags,
319 .ops = &page_cache_pipe_buf_ops, 322 .ops = &page_cache_pipe_buf_ops,
320 .spd_release = spd_release_page, 323 .spd_release = spd_release_page,
@@ -326,7 +329,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
326 index = *ppos >> PAGE_CACHE_SHIFT; 329 index = *ppos >> PAGE_CACHE_SHIFT;
327 loff = *ppos & ~PAGE_CACHE_MASK; 330 loff = *ppos & ~PAGE_CACHE_MASK;
328 req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 331 req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
329 nr_pages = min(req_pages, pipe->buffers); 332 nr_pages = min(req_pages, spd.nr_pages_max);
330 333
331 /* 334 /*
332 * Lookup the (hopefully) full range of pages we need. 335 * Lookup the (hopefully) full range of pages we need.
@@ -497,7 +500,7 @@ fill_it:
497 if (spd.nr_pages) 500 if (spd.nr_pages)
498 error = splice_to_pipe(pipe, &spd); 501 error = splice_to_pipe(pipe, &spd);
499 502
500 splice_shrink_spd(pipe, &spd); 503 splice_shrink_spd(&spd);
501 return error; 504 return error;
502} 505}
503 506
@@ -598,6 +601,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos,
598 struct splice_pipe_desc spd = { 601 struct splice_pipe_desc spd = {
599 .pages = pages, 602 .pages = pages,
600 .partial = partial, 603 .partial = partial,
604 .nr_pages_max = PIPE_DEF_BUFFERS,
601 .flags = flags, 605 .flags = flags,
602 .ops = &default_pipe_buf_ops, 606 .ops = &default_pipe_buf_ops,
603 .spd_release = spd_release_page, 607 .spd_release = spd_release_page,
@@ -608,8 +612,8 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos,
608 612
609 res = -ENOMEM; 613 res = -ENOMEM;
610 vec = __vec; 614 vec = __vec;
611 if (pipe->buffers > PIPE_DEF_BUFFERS) { 615 if (spd.nr_pages_max > PIPE_DEF_BUFFERS) {
612 vec = kmalloc(pipe->buffers * sizeof(struct iovec), GFP_KERNEL); 616 vec = kmalloc(spd.nr_pages_max * sizeof(struct iovec), GFP_KERNEL);
613 if (!vec) 617 if (!vec)
614 goto shrink_ret; 618 goto shrink_ret;
615 } 619 }
@@ -617,7 +621,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos,
617 offset = *ppos & ~PAGE_CACHE_MASK; 621 offset = *ppos & ~PAGE_CACHE_MASK;
618 nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 622 nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
619 623
620 for (i = 0; i < nr_pages && i < pipe->buffers && len; i++) { 624 for (i = 0; i < nr_pages && i < spd.nr_pages_max && len; i++) {
621 struct page *page; 625 struct page *page;
622 626
623 page = alloc_page(GFP_USER); 627 page = alloc_page(GFP_USER);
@@ -665,7 +669,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos,
665shrink_ret: 669shrink_ret:
666 if (vec != __vec) 670 if (vec != __vec)
667 kfree(vec); 671 kfree(vec);
668 splice_shrink_spd(pipe, &spd); 672 splice_shrink_spd(&spd);
669 return res; 673 return res;
670 674
671err: 675err:
@@ -1614,6 +1618,7 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
1614 struct splice_pipe_desc spd = { 1618 struct splice_pipe_desc spd = {
1615 .pages = pages, 1619 .pages = pages,
1616 .partial = partial, 1620 .partial = partial,
1621 .nr_pages_max = PIPE_DEF_BUFFERS,
1617 .flags = flags, 1622 .flags = flags,
1618 .ops = &user_page_pipe_buf_ops, 1623 .ops = &user_page_pipe_buf_ops,
1619 .spd_release = spd_release_page, 1624 .spd_release = spd_release_page,
@@ -1629,13 +1634,13 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
1629 1634
1630 spd.nr_pages = get_iovec_page_array(iov, nr_segs, spd.pages, 1635 spd.nr_pages = get_iovec_page_array(iov, nr_segs, spd.pages,
1631 spd.partial, false, 1636 spd.partial, false,
1632 pipe->buffers); 1637 spd.nr_pages_max);
1633 if (spd.nr_pages <= 0) 1638 if (spd.nr_pages <= 0)
1634 ret = spd.nr_pages; 1639 ret = spd.nr_pages;
1635 else 1640 else
1636 ret = splice_to_pipe(pipe, &spd); 1641 ret = splice_to_pipe(pipe, &spd);
1637 1642
1638 splice_shrink_spd(pipe, &spd); 1643 splice_shrink_spd(&spd);
1639 return ret; 1644 return ret;
1640} 1645}
1641 1646