Merge branch 'work.splice_read' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull VFS splice updates from Al Viro: "There's a bunch of branches this cycle, both mine and from other folks and I'd rather send pull requests separately. This one is the conversion of ->splice_read() to ITER_PIPE iov_iter (and introduction of such). Gets rid of a lot of code in fs/splice.c and elsewhere; there will be followups, but these are for the next cycle... Some pipe/splice-related cleanups from Miklos in the same branch as well" * 'work.splice_read' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: pipe: fix comment in pipe_buf_operations pipe: add pipe_buf_steal() helper pipe: add pipe_buf_confirm() helper pipe: add pipe_buf_release() helper pipe: add pipe_buf_get() helper relay: simplify relay_file_read() switch default_file_splice_read() to use of pipe-backed iov_iter switch generic_file_splice_read() to use of ->read_iter() new iov_iter flavour: pipe-backed fuse_dev_splice_read(): switch to add_to_pipe() skb_splice_bits(): get rid of callback new helper: add_to_pipe() splice: lift pipe_lock out of splice_to_pipe() splice: switch get_iovec_page_array() to iov_iter splice_to_pipe(): don't open-code wakeup_pipe_readers() consistent treatment of EFAULT on O_DIRECT read/write
This commit is contained in:
@@ -728,7 +728,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
|
||||
struct pipe_buffer *buf = cs->pipebufs;
|
||||
|
||||
if (!cs->write) {
|
||||
err = buf->ops->confirm(cs->pipe, buf);
|
||||
err = pipe_buf_confirm(cs->pipe, buf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -827,7 +827,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
|
||||
|
||||
fuse_copy_finish(cs);
|
||||
|
||||
err = buf->ops->confirm(cs->pipe, buf);
|
||||
err = pipe_buf_confirm(cs->pipe, buf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -840,7 +840,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
|
||||
if (cs->len != PAGE_SIZE)
|
||||
goto out_fallback;
|
||||
|
||||
if (buf->ops->steal(cs->pipe, buf) != 0)
|
||||
if (pipe_buf_steal(cs->pipe, buf) != 0)
|
||||
goto out_fallback;
|
||||
|
||||
newpage = buf->page;
|
||||
@@ -1341,9 +1341,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);
|
||||
@@ -1362,52 +1361,23 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = 0;
|
||||
pipe_lock(pipe);
|
||||
|
||||
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;
|
||||
bufs[page_nr].ops = &nosteal_pipe_buf_ops;
|
||||
ret = add_to_pipe(pipe, &bufs[page_nr++]);
|
||||
if (unlikely(ret < 0))
|
||||
break;
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
pipe_unlock(pipe);
|
||||
|
||||
if (do_wakeup) {
|
||||
smp_mb();
|
||||
if (waitqueue_active(&pipe->wait))
|
||||
wake_up_interruptible(&pipe->wait);
|
||||
kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
|
||||
}
|
||||
|
||||
if (total)
|
||||
ret = total;
|
||||
out:
|
||||
for (; page_nr < cs.nr_segs; page_nr++)
|
||||
put_page(bufs[page_nr].page);
|
||||
@@ -1992,7 +1962,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
|
||||
pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1);
|
||||
pipe->nrbufs--;
|
||||
} else {
|
||||
ibuf->ops->get(pipe, ibuf);
|
||||
pipe_buf_get(pipe, ibuf);
|
||||
*obuf = *ibuf;
|
||||
obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
|
||||
obuf->len = rem;
|
||||
@@ -2014,10 +1984,9 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
|
||||
|
||||
ret = fuse_dev_do_write(fud, &cs, len);
|
||||
|
||||
for (idx = 0; idx < nbuf; idx++) {
|
||||
struct pipe_buffer *buf = &bufs[idx];
|
||||
buf->ops->release(pipe, buf);
|
||||
}
|
||||
for (idx = 0; idx < nbuf; idx++)
|
||||
pipe_buf_release(pipe, &bufs[idx]);
|
||||
|
||||
out:
|
||||
kfree(bufs);
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user