forked from Minki/linux
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:
parent
fbdbacca61
commit
6c09e94a32
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user