|
@@ -1342,9 +1342,8 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
|
|
|
struct pipe_inode_info *pipe,
|
|
|
size_t len, unsigned int flags)
|
|
|
{
|
|
|
- int ret;
|
|
|
+ int total, ret;
|
|
|
int page_nr = 0;
|
|
|
- int do_wakeup = 0;
|
|
|
struct pipe_buffer *bufs;
|
|
|
struct fuse_copy_state cs;
|
|
|
struct fuse_dev *fud = fuse_get_dev(in);
|
|
@@ -1363,50 +1362,23 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
|
|
|
if (ret < 0)
|
|
|
goto out;
|
|
|
|
|
|
- ret = 0;
|
|
|
-
|
|
|
- if (!pipe->readers) {
|
|
|
- send_sig(SIGPIPE, current, 0);
|
|
|
- if (!ret)
|
|
|
- ret = -EPIPE;
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
-
|
|
|
if (pipe->nrbufs + cs.nr_segs > pipe->buffers) {
|
|
|
ret = -EIO;
|
|
|
- goto out_unlock;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
- while (page_nr < cs.nr_segs) {
|
|
|
- int newbuf = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
|
|
|
- struct pipe_buffer *buf = pipe->bufs + newbuf;
|
|
|
-
|
|
|
- buf->page = bufs[page_nr].page;
|
|
|
- buf->offset = bufs[page_nr].offset;
|
|
|
- buf->len = bufs[page_nr].len;
|
|
|
+ for (ret = total = 0; page_nr < cs.nr_segs; total += ret) {
|
|
|
/*
|
|
|
* Need to be careful about this. Having buf->ops in module
|
|
|
* code can Oops if the buffer persists after module unload.
|
|
|
*/
|
|
|
- buf->ops = &nosteal_pipe_buf_ops;
|
|
|
-
|
|
|
- pipe->nrbufs++;
|
|
|
- page_nr++;
|
|
|
- ret += buf->len;
|
|
|
-
|
|
|
- if (pipe->files)
|
|
|
- do_wakeup = 1;
|
|
|
- }
|
|
|
-
|
|
|
-out_unlock:
|
|
|
-
|
|
|
- if (do_wakeup) {
|
|
|
- smp_mb();
|
|
|
- if (waitqueue_active(&pipe->wait))
|
|
|
- wake_up_interruptible(&pipe->wait);
|
|
|
- kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
|
|
|
+ bufs[page_nr].ops = &nosteal_pipe_buf_ops;
|
|
|
+ ret = add_to_pipe(pipe, &bufs[page_nr++]);
|
|
|
+ if (unlikely(ret < 0))
|
|
|
+ break;
|
|
|
}
|
|
|
-
|
|
|
+ if (total)
|
|
|
+ ret = total;
|
|
|
out:
|
|
|
for (; page_nr < cs.nr_segs; page_nr++)
|
|
|
put_page(bufs[page_nr].page);
|