aboutsummaryrefslogtreecommitdiffstats
path: root/fs/splice.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2006-04-10 09:18:35 -0400
committerJens Axboe <axboe@suse.de>2006-04-10 09:18:35 -0400
commit3a326a2ce88e71d00ac0d133e314a3342a7709f8 (patch)
tree3a3cf55be19311c04d195e37baec9f49c4015b18 /fs/splice.c
parent0b749ce3802428007a37870eb51ba3c0bdf90857 (diff)
[PATCH] introduce a "kernel-internal pipe object" abstraction
separate out the 'internal pipe object' abstraction, and make it usable to splice. This cleans up and fixes several aspects of the internal splice APIs and the pipe code: - pipes: the allocation and freeing of pipe_inode_info is now more symmetric and more streamlined with existing kernel practices. - splice: small micro-optimization: less pointer dereferencing in splice methods Signed-off-by: Ingo Molnar <mingo@elte.hu> Update XFS for the ->splice_read/->splice_write changes. Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'fs/splice.c')
-rw-r--r--fs/splice.c122
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 */
139static ssize_t move_to_pipe(struct inode *inode, struct page **pages, 139static 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
235static int __generic_file_splice_read(struct file *in, struct inode *pipe, 234static 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 */
301ssize_t generic_file_splice_read(struct file *in, struct inode *pipe, 301ssize_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 */
512static ssize_t move_from_pipe(struct inode *inode, struct file *out, 513static 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 */
628ssize_t generic_file_splice_write(struct inode *inode, struct file *out, 629ssize_t
629 size_t len, unsigned int flags) 630generic_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 */
667ssize_t generic_splice_sendpage(struct inode *inode, struct file *out, 671ssize_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
673EXPORT_SYMBOL(generic_splice_sendpage); 677EXPORT_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 */
678static long do_splice_from(struct inode *pipe, struct file *out, size_t len, 682static 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 */
701static long do_splice_to(struct file *in, struct inode *pipe, size_t len, 705static 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,
732static long do_splice(struct file *in, struct file *out, size_t len, 736static 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;