aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-07-29 20:09:39 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-07-29 20:09:39 -0400
commit73bcc49959e4e40911dd0dd634bf1b353827df66 (patch)
tree6b0c1d440c490a65c51ab5cf5aee7095cb4089d3 /fs/splice.c
parent8447c4d15e357a458c9051ddc84aa6c8b9c27000 (diff)
parent28a33cbc24e4256c143dce96c7d93bf423229f92 (diff)
Merge tag 'v3.5'
Linux 3.5 * tag 'v3.5': (1242 commits) Linux 3.5 Remove SYSTEM_SUSPEND_DISK system state kdb: Switch to nolock variants of kmsg_dump functions printk: Implement some unlocked kmsg_dump functions printk: Remove kdb_syslog_data kdb: Revive dmesg command dm raid1: set discard_zeroes_data_unsupported dm thin: do not send discards to shared blocks dm raid1: fix crash with mirror recovery and discard pnfs-obj: Fix __r4w_get_page when offset is beyond i_size pnfs-obj: don't leak objio_state if ore_write/read fails ore: Unlock r4w pages in exact reverse order of locking ore: Remove support of partial IO request (NFS crash) ore: Fix NFS crash by supporting any unaligned RAID IO UBIFS: fix a bug in empty space fix-up cx25821: Remove bad strcpy to read-only char* HID: hid-multitouch: add support for Zytronic panels MIPS: PCI: Move fixups from __init to __devinit. MIPS: Fix bug.h MIPS build regression MIPS: sync-r4k: remove redundant irq operation ...
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