Commit 7f024647 authored by Al Viro's avatar Al Viro

9p: convert to advancing variant of iov_iter_get_pages_alloc()

that one is somewhat clumsier than usual and needs serious testing.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent dc5801f6
...@@ -1491,7 +1491,7 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to, ...@@ -1491,7 +1491,7 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
struct p9_client *clnt = fid->clnt; struct p9_client *clnt = fid->clnt;
struct p9_req_t *req; struct p9_req_t *req;
int count = iov_iter_count(to); int count = iov_iter_count(to);
int rsize, non_zc = 0; int rsize, received, non_zc = 0;
char *dataptr; char *dataptr;
*err = 0; *err = 0;
...@@ -1520,36 +1520,40 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to, ...@@ -1520,36 +1520,40 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
} }
if (IS_ERR(req)) { if (IS_ERR(req)) {
*err = PTR_ERR(req); *err = PTR_ERR(req);
if (!non_zc)
iov_iter_revert(to, count - iov_iter_count(to));
return 0; return 0;
} }
*err = p9pdu_readf(&req->rc, clnt->proto_version, *err = p9pdu_readf(&req->rc, clnt->proto_version,
"D", &count, &dataptr); "D", &received, &dataptr);
if (*err) { if (*err) {
if (!non_zc)
iov_iter_revert(to, count - iov_iter_count(to));
trace_9p_protocol_dump(clnt, &req->rc); trace_9p_protocol_dump(clnt, &req->rc);
p9_tag_remove(clnt, req); p9_tag_remove(clnt, req);
return 0; return 0;
} }
if (rsize < count) { if (rsize < received) {
pr_err("bogus RREAD count (%d > %d)\n", count, rsize); pr_err("bogus RREAD count (%d > %d)\n", received, rsize);
count = rsize; received = rsize;
} }
p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count); p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
if (non_zc) { if (non_zc) {
int n = copy_to_iter(dataptr, count, to); int n = copy_to_iter(dataptr, received, to);
if (n != count) { if (n != received) {
*err = -EFAULT; *err = -EFAULT;
p9_tag_remove(clnt, req); p9_tag_remove(clnt, req);
return n; return n;
} }
} else { } else {
iov_iter_advance(to, count); iov_iter_revert(to, count - received - iov_iter_count(to));
} }
p9_tag_remove(clnt, req); p9_tag_remove(clnt, req);
return count; return received;
} }
EXPORT_SYMBOL(p9_client_read_once); EXPORT_SYMBOL(p9_client_read_once);
...@@ -1567,6 +1571,7 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) ...@@ -1567,6 +1571,7 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
while (iov_iter_count(from)) { while (iov_iter_count(from)) {
int count = iov_iter_count(from); int count = iov_iter_count(from);
int rsize = fid->iounit; int rsize = fid->iounit;
int written;
if (!rsize || rsize > clnt->msize - P9_IOHDRSZ) if (!rsize || rsize > clnt->msize - P9_IOHDRSZ)
rsize = clnt->msize - P9_IOHDRSZ; rsize = clnt->msize - P9_IOHDRSZ;
...@@ -1584,27 +1589,29 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) ...@@ -1584,27 +1589,29 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
offset, rsize, from); offset, rsize, from);
} }
if (IS_ERR(req)) { if (IS_ERR(req)) {
iov_iter_revert(from, count - iov_iter_count(from));
*err = PTR_ERR(req); *err = PTR_ERR(req);
break; break;
} }
*err = p9pdu_readf(&req->rc, clnt->proto_version, "d", &count); *err = p9pdu_readf(&req->rc, clnt->proto_version, "d", &written);
if (*err) { if (*err) {
iov_iter_revert(from, count - iov_iter_count(from));
trace_9p_protocol_dump(clnt, &req->rc); trace_9p_protocol_dump(clnt, &req->rc);
p9_tag_remove(clnt, req); p9_tag_remove(clnt, req);
break; break;
} }
if (rsize < count) { if (rsize < written) {
pr_err("bogus RWRITE count (%d > %d)\n", count, rsize); pr_err("bogus RWRITE count (%d > %d)\n", written, rsize);
count = rsize; written = rsize;
} }
p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count); p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
p9_tag_remove(clnt, req); p9_tag_remove(clnt, req);
iov_iter_advance(from, count); iov_iter_revert(from, count - written - iov_iter_count(from));
total += count; total += written;
offset += count; offset += written;
} }
return total; return total;
} }
......
...@@ -63,9 +63,8 @@ static size_t ...@@ -63,9 +63,8 @@ static size_t
pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t size) pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t size)
{ {
size_t len = min(pdu->capacity - pdu->size, size); size_t len = min(pdu->capacity - pdu->size, size);
struct iov_iter i = *from;
if (!copy_from_iter_full(&pdu->sdata[pdu->size], len, &i)) if (!copy_from_iter_full(&pdu->sdata[pdu->size], len, from))
len = 0; len = 0;
pdu->size += len; pdu->size += len;
......
...@@ -331,7 +331,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, ...@@ -331,7 +331,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
if (err == -ERESTARTSYS) if (err == -ERESTARTSYS)
return err; return err;
} }
n = iov_iter_get_pages_alloc(data, pages, count, offs); n = iov_iter_get_pages_alloc2(data, pages, count, offs);
if (n < 0) if (n < 0)
return n; return n;
*need_drop = 1; *need_drop = 1;
...@@ -373,6 +373,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, ...@@ -373,6 +373,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
(*pages)[index] = kmap_to_page(p); (*pages)[index] = kmap_to_page(p);
p += PAGE_SIZE; p += PAGE_SIZE;
} }
iov_iter_advance(data, len);
return len; return len;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment