diff options
Diffstat (limited to 'fs/splice.c')
-rw-r--r-- | fs/splice.c | 122 |
1 files changed, 63 insertions, 59 deletions
diff --git a/fs/splice.c b/fs/splice.c index 9bfd6af0cf45..ed91a62402e0 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -136,34 +136,33 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = { | |||
136 | * Pipe output worker. This sets up our pipe format with the page cache | 136 | * Pipe output worker. This sets up our pipe format with the page cache |
137 | * pipe buffer operations. Otherwise very similar to the regular pipe_writev(). | 137 | * pipe buffer operations. Otherwise very similar to the regular pipe_writev(). |
138 | */ | 138 | */ |
139 | static ssize_t move_to_pipe(struct inode *inode, struct page **pages, | 139 | static ssize_t move_to_pipe(struct pipe_inode_info *pipe, struct page **pages, |
140 | int nr_pages, unsigned long offset, | 140 | int nr_pages, unsigned long offset, |
141 | unsigned long len, unsigned int flags) | 141 | unsigned long len, unsigned int flags) |
142 | { | 142 | { |
143 | struct pipe_inode_info *info; | ||
144 | int ret, do_wakeup, i; | 143 | int ret, do_wakeup, i; |
145 | 144 | ||
146 | ret = 0; | 145 | ret = 0; |
147 | do_wakeup = 0; | 146 | do_wakeup = 0; |
148 | i = 0; | 147 | i = 0; |
149 | 148 | ||
150 | mutex_lock(PIPE_MUTEX(*inode)); | 149 | if (pipe->inode) |
150 | mutex_lock(&pipe->inode->i_mutex); | ||
151 | 151 | ||
152 | info = inode->i_pipe; | ||
153 | for (;;) { | 152 | for (;;) { |
154 | int bufs; | 153 | int bufs; |
155 | 154 | ||
156 | if (!PIPE_READERS(*inode)) { | 155 | if (!pipe->readers) { |
157 | send_sig(SIGPIPE, current, 0); | 156 | send_sig(SIGPIPE, current, 0); |
158 | if (!ret) | 157 | if (!ret) |
159 | ret = -EPIPE; | 158 | ret = -EPIPE; |
160 | break; | 159 | break; |
161 | } | 160 | } |
162 | 161 | ||
163 | bufs = info->nrbufs; | 162 | bufs = pipe->nrbufs; |
164 | if (bufs < PIPE_BUFFERS) { | 163 | if (bufs < PIPE_BUFFERS) { |
165 | int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS - 1); | 164 | int newbuf = (pipe->curbuf + bufs) & (PIPE_BUFFERS - 1); |
166 | struct pipe_buffer *buf = info->bufs + newbuf; | 165 | struct pipe_buffer *buf = pipe->bufs + newbuf; |
167 | struct page *page = pages[i++]; | 166 | struct page *page = pages[i++]; |
168 | unsigned long this_len; | 167 | unsigned long this_len; |
169 | 168 | ||
@@ -175,7 +174,7 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages, | |||
175 | buf->offset = offset; | 174 | buf->offset = offset; |
176 | buf->len = this_len; | 175 | buf->len = this_len; |
177 | buf->ops = &page_cache_pipe_buf_ops; | 176 | buf->ops = &page_cache_pipe_buf_ops; |
178 | info->nrbufs = ++bufs; | 177 | pipe->nrbufs = ++bufs; |
179 | do_wakeup = 1; | 178 | do_wakeup = 1; |
180 | 179 | ||
181 | ret += this_len; | 180 | ret += this_len; |
@@ -205,25 +204,25 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages, | |||
205 | 204 | ||
206 | if (do_wakeup) { | 205 | if (do_wakeup) { |
207 | smp_mb(); | 206 | smp_mb(); |
208 | if (waitqueue_active(PIPE_WAIT(*inode))) | 207 | if (waitqueue_active(&pipe->wait)) |
209 | wake_up_interruptible_sync(PIPE_WAIT(*inode)); | 208 | wake_up_interruptible_sync(&pipe->wait); |
210 | kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, | 209 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); |
211 | POLL_IN); | ||
212 | do_wakeup = 0; | 210 | do_wakeup = 0; |
213 | } | 211 | } |
214 | 212 | ||
215 | PIPE_WAITING_WRITERS(*inode)++; | 213 | pipe->waiting_writers++; |
216 | pipe_wait(inode); | 214 | pipe_wait(pipe); |
217 | PIPE_WAITING_WRITERS(*inode)--; | 215 | pipe->waiting_writers--; |
218 | } | 216 | } |
219 | 217 | ||
220 | mutex_unlock(PIPE_MUTEX(*inode)); | 218 | if (pipe->inode) |
219 | mutex_unlock(&pipe->inode->i_mutex); | ||
221 | 220 | ||
222 | if (do_wakeup) { | 221 | if (do_wakeup) { |
223 | smp_mb(); | 222 | smp_mb(); |
224 | if (waitqueue_active(PIPE_WAIT(*inode))) | 223 | if (waitqueue_active(&pipe->wait)) |
225 | wake_up_interruptible(PIPE_WAIT(*inode)); | 224 | wake_up_interruptible(&pipe->wait); |
226 | kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN); | 225 | kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); |
227 | } | 226 | } |
228 | 227 | ||
229 | while (i < nr_pages) | 228 | while (i < nr_pages) |
@@ -232,8 +231,9 @@ static ssize_t move_to_pipe(struct inode *inode, struct page **pages, | |||
232 | return ret; | 231 | return ret; |
233 | } | 232 | } |
234 | 233 | ||
235 | static int __generic_file_splice_read(struct file *in, struct inode *pipe, | 234 | static int |
236 | size_t len, unsigned int flags) | 235 | __generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, |
236 | size_t len, unsigned int flags) | ||
237 | { | 237 | { |
238 | struct address_space *mapping = in->f_mapping; | 238 | struct address_space *mapping = in->f_mapping; |
239 | unsigned int offset, nr_pages; | 239 | unsigned int offset, nr_pages; |
@@ -298,7 +298,7 @@ static int __generic_file_splice_read(struct file *in, struct inode *pipe, | |||
298 | * Will read pages from given file and fill them into a pipe. | 298 | * Will read pages from given file and fill them into a pipe. |
299 | * | 299 | * |
300 | */ | 300 | */ |
301 | ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, | 301 | ssize_t generic_file_splice_read(struct file *in, struct pipe_inode_info *pipe, |
302 | size_t len, unsigned int flags) | 302 | size_t len, unsigned int flags) |
303 | { | 303 | { |
304 | ssize_t spliced; | 304 | ssize_t spliced; |
@@ -306,6 +306,7 @@ ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, | |||
306 | 306 | ||
307 | ret = 0; | 307 | ret = 0; |
308 | spliced = 0; | 308 | spliced = 0; |
309 | |||
309 | while (len) { | 310 | while (len) { |
310 | ret = __generic_file_splice_read(in, pipe, len, flags); | 311 | ret = __generic_file_splice_read(in, pipe, len, flags); |
311 | 312 | ||
@@ -509,11 +510,10 @@ typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, | |||
509 | * key here is the 'actor' worker passed in that actually moves the data | 510 | * key here is the 'actor' worker passed in that actually moves the data |
510 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. | 511 | * to the wanted destination. See pipe_to_file/pipe_to_sendpage above. |
511 | */ | 512 | */ |
512 | static ssize_t move_from_pipe(struct inode *inode, struct file *out, | 513 | static ssize_t move_from_pipe(struct pipe_inode_info *pipe, struct file *out, |
513 | size_t len, unsigned int flags, | 514 | size_t len, unsigned int flags, |
514 | splice_actor *actor) | 515 | splice_actor *actor) |
515 | { | 516 | { |
516 | struct pipe_inode_info *info; | ||
517 | int ret, do_wakeup, err; | 517 | int ret, do_wakeup, err; |
518 | struct splice_desc sd; | 518 | struct splice_desc sd; |
519 | 519 | ||
@@ -525,22 +525,22 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, | |||
525 | sd.file = out; | 525 | sd.file = out; |
526 | sd.pos = out->f_pos; | 526 | sd.pos = out->f_pos; |
527 | 527 | ||
528 | mutex_lock(PIPE_MUTEX(*inode)); | 528 | if (pipe->inode) |
529 | mutex_lock(&pipe->inode->i_mutex); | ||
529 | 530 | ||
530 | info = inode->i_pipe; | ||
531 | for (;;) { | 531 | for (;;) { |
532 | int bufs = info->nrbufs; | 532 | int bufs = pipe->nrbufs; |
533 | 533 | ||
534 | if (bufs) { | 534 | if (bufs) { |
535 | int curbuf = info->curbuf; | 535 | int curbuf = pipe->curbuf; |
536 | struct pipe_buffer *buf = info->bufs + curbuf; | 536 | struct pipe_buffer *buf = pipe->bufs + curbuf; |
537 | struct pipe_buf_operations *ops = buf->ops; | 537 | struct pipe_buf_operations *ops = buf->ops; |
538 | 538 | ||
539 | sd.len = buf->len; | 539 | sd.len = buf->len; |
540 | if (sd.len > sd.total_len) | 540 | if (sd.len > sd.total_len) |
541 | sd.len = sd.total_len; | 541 | sd.len = sd.total_len; |
542 | 542 | ||
543 | err = actor(info, buf, &sd); | 543 | err = actor(pipe, buf, &sd); |
544 | if (err) { | 544 | if (err) { |
545 | if (!ret && err != -ENODATA) | 545 | if (!ret && err != -ENODATA) |
546 | ret = err; | 546 | ret = err; |
@@ -553,10 +553,10 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, | |||
553 | buf->len -= sd.len; | 553 | buf->len -= sd.len; |
554 | if (!buf->len) { | 554 | if (!buf->len) { |
555 | buf->ops = NULL; | 555 | buf->ops = NULL; |
556 | ops->release(info, buf); | 556 | ops->release(pipe, buf); |
557 | curbuf = (curbuf + 1) & (PIPE_BUFFERS - 1); | 557 | curbuf = (curbuf + 1) & (PIPE_BUFFERS - 1); |
558 | info->curbuf = curbuf; | 558 | pipe->curbuf = curbuf; |
559 | info->nrbufs = --bufs; | 559 | pipe->nrbufs = --bufs; |
560 | do_wakeup = 1; | 560 | do_wakeup = 1; |
561 | } | 561 | } |
562 | 562 | ||
@@ -568,9 +568,9 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, | |||
568 | 568 | ||
569 | if (bufs) | 569 | if (bufs) |
570 | continue; | 570 | continue; |
571 | if (!PIPE_WRITERS(*inode)) | 571 | if (!pipe->writers) |
572 | break; | 572 | break; |
573 | if (!PIPE_WAITING_WRITERS(*inode)) { | 573 | if (!pipe->waiting_writers) { |
574 | if (ret) | 574 | if (ret) |
575 | break; | 575 | break; |
576 | } | 576 | } |
@@ -589,22 +589,23 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, | |||
589 | 589 | ||
590 | if (do_wakeup) { | 590 | if (do_wakeup) { |
591 | smp_mb(); | 591 | smp_mb(); |
592 | if (waitqueue_active(PIPE_WAIT(*inode))) | 592 | if (waitqueue_active(&pipe->wait)) |
593 | wake_up_interruptible_sync(PIPE_WAIT(*inode)); | 593 | wake_up_interruptible_sync(&pipe->wait); |
594 | kill_fasync(PIPE_FASYNC_WRITERS(*inode),SIGIO,POLL_OUT); | 594 | kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); |
595 | do_wakeup = 0; | 595 | do_wakeup = 0; |
596 | } | 596 | } |
597 | 597 | ||
598 | pipe_wait(inode); | 598 | pipe_wait(pipe); |
599 | } | 599 | } |
600 | 600 | ||
601 | mutex_unlock(PIPE_MUTEX(*inode)); | 601 | if (pipe->inode) |
602 | mutex_unlock(&pipe->inode->i_mutex); | ||
602 | 603 | ||
603 | if (do_wakeup) { | 604 | if (do_wakeup) { |
604 | smp_mb(); | 605 | smp_mb(); |
605 | if (waitqueue_active(PIPE_WAIT(*inode))) | 606 | if (waitqueue_active(&pipe->wait)) |
606 | wake_up_interruptible(PIPE_WAIT(*inode)); | 607 | wake_up_interruptible(&pipe->wait); |
607 | kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); | 608 | kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); |
608 | } | 609 | } |
609 | 610 | ||
610 | mutex_lock(&out->f_mapping->host->i_mutex); | 611 | mutex_lock(&out->f_mapping->host->i_mutex); |
@@ -616,7 +617,7 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, | |||
616 | 617 | ||
617 | /** | 618 | /** |
618 | * generic_file_splice_write - splice data from a pipe to a file | 619 | * generic_file_splice_write - splice data from a pipe to a file |
619 | * @inode: pipe inode | 620 | * @pipe: pipe info |
620 | * @out: file to write to | 621 | * @out: file to write to |
621 | * @len: number of bytes to splice | 622 | * @len: number of bytes to splice |
622 | * @flags: splice modifier flags | 623 | * @flags: splice modifier flags |
@@ -625,11 +626,14 @@ static ssize_t move_from_pipe(struct inode *inode, struct file *out, | |||
625 | * the given pipe inode to the given file. | 626 | * the given pipe inode to the given file. |
626 | * | 627 | * |
627 | */ | 628 | */ |
628 | ssize_t generic_file_splice_write(struct inode *inode, struct file *out, | 629 | ssize_t |
629 | size_t len, unsigned int flags) | 630 | generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, |
631 | size_t len, unsigned int flags) | ||
630 | { | 632 | { |
631 | struct address_space *mapping = out->f_mapping; | 633 | struct address_space *mapping = out->f_mapping; |
632 | ssize_t ret = move_from_pipe(inode, out, len, flags, pipe_to_file); | 634 | ssize_t ret; |
635 | |||
636 | ret = move_from_pipe(pipe, out, len, flags, pipe_to_file); | ||
633 | 637 | ||
634 | /* | 638 | /* |
635 | * if file or inode is SYNC and we actually wrote some data, sync it | 639 | * if file or inode is SYNC and we actually wrote some data, sync it |
@@ -664,10 +668,10 @@ EXPORT_SYMBOL(generic_file_splice_write); | |||
664 | * is involved. | 668 | * is involved. |
665 | * | 669 | * |
666 | */ | 670 | */ |
667 | ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, | 671 | ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, |
668 | size_t len, unsigned int flags) | 672 | size_t len, unsigned int flags) |
669 | { | 673 | { |
670 | return move_from_pipe(inode, out, len, flags, pipe_to_sendpage); | 674 | return move_from_pipe(pipe, out, len, flags, pipe_to_sendpage); |
671 | } | 675 | } |
672 | 676 | ||
673 | EXPORT_SYMBOL(generic_splice_sendpage); | 677 | EXPORT_SYMBOL(generic_splice_sendpage); |
@@ -675,8 +679,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); | |||
675 | /* | 679 | /* |
676 | * Attempt to initiate a splice from pipe to file. | 680 | * Attempt to initiate a splice from pipe to file. |
677 | */ | 681 | */ |
678 | static long do_splice_from(struct inode *pipe, struct file *out, size_t len, | 682 | static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, |
679 | unsigned int flags) | 683 | size_t len, unsigned int flags) |
680 | { | 684 | { |
681 | loff_t pos; | 685 | loff_t pos; |
682 | int ret; | 686 | int ret; |
@@ -698,8 +702,8 @@ static long do_splice_from(struct inode *pipe, struct file *out, size_t len, | |||
698 | /* | 702 | /* |
699 | * Attempt to initiate a splice from a file to a pipe. | 703 | * Attempt to initiate a splice from a file to a pipe. |
700 | */ | 704 | */ |
701 | static long do_splice_to(struct file *in, struct inode *pipe, size_t len, | 705 | static long do_splice_to(struct file *in, struct pipe_inode_info *pipe, |
702 | unsigned int flags) | 706 | size_t len, unsigned int flags) |
703 | { | 707 | { |
704 | loff_t pos, isize, left; | 708 | loff_t pos, isize, left; |
705 | int ret; | 709 | int ret; |
@@ -732,14 +736,14 @@ static long do_splice_to(struct file *in, struct inode *pipe, size_t len, | |||
732 | static long do_splice(struct file *in, struct file *out, size_t len, | 736 | static long do_splice(struct file *in, struct file *out, size_t len, |
733 | unsigned int flags) | 737 | unsigned int flags) |
734 | { | 738 | { |
735 | struct inode *pipe; | 739 | struct pipe_inode_info *pipe; |
736 | 740 | ||
737 | pipe = in->f_dentry->d_inode; | 741 | pipe = in->f_dentry->d_inode->i_pipe; |
738 | if (pipe->i_pipe) | 742 | if (pipe) |
739 | return do_splice_from(pipe, out, len, flags); | 743 | return do_splice_from(pipe, out, len, flags); |
740 | 744 | ||
741 | pipe = out->f_dentry->d_inode; | 745 | pipe = out->f_dentry->d_inode->i_pipe; |
742 | if (pipe->i_pipe) | 746 | if (pipe) |
743 | return do_splice_to(in, pipe, len, flags); | 747 | return do_splice_to(in, pipe, len, flags); |
744 | 748 | ||
745 | return -EINVAL; | 749 | return -EINVAL; |