aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-04-01 23:42:28 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-04-11 22:28:27 -0400
commite1200fe68f20759f359698f8a8dc81d06d1265f5 (patch)
tree2f6a596be0d8d2aa759687be4c0e9f4e0ecc1723 /net
parent9565a5445240cd441f2c670aa7260ee8eb5dff79 (diff)
9p: switch p9_client_read() to passing struct iov_iter *
... and make it loop Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'net')
-rw-r--r--net/9p/client.c124
1 files changed, 61 insertions, 63 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index aa38cfeb8615..18583bb89db6 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1534,79 +1534,77 @@ error:
1534EXPORT_SYMBOL(p9_client_unlinkat); 1534EXPORT_SYMBOL(p9_client_unlinkat);
1535 1535
1536int 1536int
1537p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, 1537p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
1538 u32 count)
1539{ 1538{
1540 char *dataptr; 1539 struct p9_client *clnt = fid->clnt;
1541 struct p9_req_t *req; 1540 struct p9_req_t *req;
1542 struct p9_client *clnt; 1541 int total = 0;
1543 int err, rsize, non_zc = 0;
1544 struct iov_iter to;
1545 union {
1546 struct kvec kv;
1547 struct iovec iov;
1548 } v;
1549
1550 if (data) {
1551 v.kv.iov_base = data;
1552 v.kv.iov_len = count;
1553 iov_iter_kvec(&to, ITER_KVEC | READ, &v.kv, 1, count);
1554 } else {
1555 v.iov.iov_base = udata;
1556 v.iov.iov_len = count;
1557 iov_iter_init(&to, READ, &v.iov, 1, count);
1558 }
1559 1542
1560 p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", 1543 p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n",
1561 fid->fid, (unsigned long long) offset, count); 1544 fid->fid, (unsigned long long) offset, (int)iov_iter_count(to));
1562 err = 0; 1545
1563 clnt = fid->clnt; 1546 while (iov_iter_count(to)) {
1564 1547 int count = iov_iter_count(to);
1565 rsize = fid->iounit; 1548 int rsize, non_zc = 0;
1566 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) 1549 char *dataptr;
1567 rsize = clnt->msize - P9_IOHDRSZ; 1550
1551 rsize = fid->iounit;
1552 if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
1553 rsize = clnt->msize - P9_IOHDRSZ;
1568 1554
1569 if (count < rsize) 1555 if (count < rsize)
1570 rsize = count; 1556 rsize = count;
1571 1557
1572 /* Don't bother zerocopy for small IO (< 1024) */ 1558 /* Don't bother zerocopy for small IO (< 1024) */
1573 if (clnt->trans_mod->zc_request && rsize > 1024) { 1559 if (clnt->trans_mod->zc_request && rsize > 1024) {
1574 /* 1560 /*
1575 * response header len is 11 1561 * response header len is 11
1576 * PDU Header(7) + IO Size (4) 1562 * PDU Header(7) + IO Size (4)
1577 */ 1563 */
1578 req = p9_client_zc_rpc(clnt, P9_TREAD, &to, NULL, rsize, 0, 1564 req = p9_client_zc_rpc(clnt, P9_TREAD, to, NULL, rsize,
1579 11, "dqd", fid->fid, 1565 0, 11, "dqd", fid->fid,
1580 offset, rsize); 1566 offset, rsize);
1581 } else { 1567 } else {
1582 non_zc = 1; 1568 non_zc = 1;
1583 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, 1569 req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
1584 rsize); 1570 rsize);
1585 } 1571 }
1586 if (IS_ERR(req)) { 1572 if (IS_ERR(req)) {
1587 err = PTR_ERR(req); 1573 *err = PTR_ERR(req);
1588 goto error; 1574 break;
1589 } 1575 }
1590 1576
1591 err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); 1577 *err = p9pdu_readf(req->rc, clnt->proto_version,
1592 if (err) { 1578 "D", &count, &dataptr);
1593 trace_9p_protocol_dump(clnt, req->rc); 1579 if (*err) {
1594 goto free_and_error; 1580 trace_9p_protocol_dump(clnt, req->rc);
1595 } 1581 p9_free_req(clnt, req);
1582 break;
1583 }
1596 1584
1597 p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count); 1585 p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1586 if (!count) {
1587 p9_free_req(clnt, req);
1588 break;
1589 }
1598 1590
1599 if (non_zc && copy_to_iter(dataptr, count, &to) != count) { 1591 if (non_zc) {
1600 err = -EFAULT; 1592 int n = copy_to_iter(dataptr, count, to);
1601 goto free_and_error; 1593 total += n;
1594 offset += n;
1595 if (n != count) {
1596 *err = -EFAULT;
1597 p9_free_req(clnt, req);
1598 break;
1599 }
1600 } else {
1601 iov_iter_advance(to, count);
1602 total += count;
1603 offset += count;
1604 }
1605 p9_free_req(clnt, req);
1602 } 1606 }
1603 p9_free_req(clnt, req); 1607 return total;
1604 return count;
1605
1606free_and_error:
1607 p9_free_req(clnt, req);
1608error:
1609 return err;
1610} 1608}
1611EXPORT_SYMBOL(p9_client_read); 1609EXPORT_SYMBOL(p9_client_read);
1612 1610