fuse: use iov_iter_get_pages() for non-splice path

store reference to iter instead of that to iovec

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2015-04-03 22:06:08 -04:00
parent fbdbacca61
commit 6c09e94a32
1 changed files with 17 additions and 24 deletions

View File

@ -710,28 +710,26 @@ struct fuse_copy_state {
struct fuse_conn *fc; struct fuse_conn *fc;
int write; int write;
struct fuse_req *req; struct fuse_req *req;
const struct iovec *iov; struct iov_iter *iter;
struct pipe_buffer *pipebufs; struct pipe_buffer *pipebufs;
struct pipe_buffer *currbuf; struct pipe_buffer *currbuf;
struct pipe_inode_info *pipe; struct pipe_inode_info *pipe;
unsigned long nr_segs; unsigned long nr_segs;
unsigned long seglen;
unsigned long addr;
struct page *pg; struct page *pg;
unsigned len; unsigned len;
unsigned offset; unsigned offset;
unsigned move_pages:1; unsigned move_pages:1;
}; };
static void fuse_copy_init(struct fuse_copy_state *cs, struct fuse_conn *fc, static void fuse_copy_init(struct fuse_copy_state *cs,
struct fuse_conn *fc,
int write, int write,
const struct iovec *iov, unsigned long nr_segs) struct iov_iter *iter)
{ {
memset(cs, 0, sizeof(*cs)); memset(cs, 0, sizeof(*cs));
cs->fc = fc; cs->fc = fc;
cs->write = write; cs->write = write;
cs->iov = iov; cs->iter = iter;
cs->nr_segs = nr_segs;
} }
/* Unmap and put previous page of userspace buffer */ /* Unmap and put previous page of userspace buffer */
@ -799,22 +797,16 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
cs->nr_segs++; cs->nr_segs++;
} }
} else { } else {
if (!cs->seglen) { size_t off;
BUG_ON(!cs->nr_segs); err = iov_iter_get_pages(cs->iter, &page, PAGE_SIZE, 1, &off);
cs->seglen = cs->iov[0].iov_len;
cs->addr = (unsigned long) cs->iov[0].iov_base;
cs->iov++;
cs->nr_segs--;
}
err = get_user_pages_fast(cs->addr, 1, cs->write, &page);
if (err < 0) if (err < 0)
return err; return err;
BUG_ON(err != 1); BUG_ON(!err);
cs->len = err;
cs->offset = off;
cs->pg = page; cs->pg = page;
cs->offset = cs->addr % PAGE_SIZE; cs->offset = off;
cs->len = min(PAGE_SIZE - cs->offset, cs->seglen); iov_iter_advance(cs->iter, err);
cs->seglen -= cs->len;
cs->addr += cs->len;
} }
return lock_request(cs->fc, cs->req); return lock_request(cs->fc, cs->req);
@ -1374,7 +1366,7 @@ static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to)
if (!iter_is_iovec(to)) if (!iter_is_iovec(to))
return -EINVAL; return -EINVAL;
fuse_copy_init(&cs, fc, 1, to->iov, to->nr_segs); fuse_copy_init(&cs, fc, 1, to);
return fuse_dev_do_read(fc, file, &cs, iov_iter_count(to)); return fuse_dev_do_read(fc, file, &cs, iov_iter_count(to));
} }
@ -1396,7 +1388,7 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
if (!bufs) if (!bufs)
return -ENOMEM; return -ENOMEM;
fuse_copy_init(&cs, fc, 1, NULL, 0); fuse_copy_init(&cs, fc, 1, NULL);
cs.pipebufs = bufs; cs.pipebufs = bufs;
cs.pipe = pipe; cs.pipe = pipe;
ret = fuse_dev_do_read(fc, in, &cs, len); ret = fuse_dev_do_read(fc, in, &cs, len);
@ -1982,7 +1974,7 @@ static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from)
if (!iter_is_iovec(from)) if (!iter_is_iovec(from))
return -EINVAL; return -EINVAL;
fuse_copy_init(&cs, fc, 0, from->iov, from->nr_segs); fuse_copy_init(&cs, fc, 0, from);
return fuse_dev_do_write(fc, &cs, iov_iter_count(from)); return fuse_dev_do_write(fc, &cs, iov_iter_count(from));
} }
@ -2047,8 +2039,9 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
} }
pipe_unlock(pipe); pipe_unlock(pipe);
fuse_copy_init(&cs, fc, 0, NULL, nbuf); fuse_copy_init(&cs, fc, 0, NULL);
cs.pipebufs = bufs; cs.pipebufs = bufs;
cs.nr_segs = nbuf;
cs.pipe = pipe; cs.pipe = pipe;
if (flags & SPLICE_F_MOVE) if (flags & SPLICE_F_MOVE)