aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/client.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-04-01 19:57:53 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-04-11 22:28:25 -0400
commit4f3b35c157e43107cc7e1f1aa06694e8b22e10bb (patch)
tree2e871c8698529878f93c225b818f4aa4b871f3c6 /net/9p/client.c
parent6e242a1ceeb1bcf55ffefa84d3079f711fe8a667 (diff)
net/9p: switch the guts of p9_client_{read,write}() to iov_iter
... and have get_user_pages_fast() mapping fewer pages than requested to generate a short read/write. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'net/9p/client.c')
-rw-r--r--net/9p/client.c117
1 files changed, 59 insertions, 58 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index e86a9bea1d16..9ef5d85f082f 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -34,6 +34,7 @@
34#include <linux/slab.h> 34#include <linux/slab.h>
35#include <linux/sched.h> 35#include <linux/sched.h>
36#include <linux/uaccess.h> 36#include <linux/uaccess.h>
37#include <linux/uio.h>
37#include <net/9p/9p.h> 38#include <net/9p/9p.h>
38#include <linux/parser.h> 39#include <linux/parser.h>
39#include <net/9p/client.h> 40#include <net/9p/client.h>
@@ -555,7 +556,7 @@ out_err:
555 */ 556 */
556 557
557static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, 558static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
558 char *uidata, int in_hdrlen, int kern_buf) 559 struct iov_iter *uidata, int in_hdrlen)
559{ 560{
560 int err; 561 int err;
561 int ecode; 562 int ecode;
@@ -591,16 +592,11 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
591 ename = &req->rc->sdata[req->rc->offset]; 592 ename = &req->rc->sdata[req->rc->offset];
592 if (len > inline_len) { 593 if (len > inline_len) {
593 /* We have error in external buffer */ 594 /* We have error in external buffer */
594 if (kern_buf) { 595 err = copy_from_iter(ename + inline_len,
595 memcpy(ename + inline_len, uidata, 596 len - inline_len, uidata);
596 len - inline_len); 597 if (err != len - inline_len) {
597 } else { 598 err = -EFAULT;
598 err = copy_from_user(ename + inline_len, 599 goto out_err;
599 uidata, len - inline_len);
600 if (err) {
601 err = -EFAULT;
602 goto out_err;
603 }
604 } 600 }
605 } 601 }
606 ename = NULL; 602 ename = NULL;
@@ -806,8 +802,8 @@ reterr:
806 * p9_client_zc_rpc - issue a request and wait for a response 802 * p9_client_zc_rpc - issue a request and wait for a response
807 * @c: client session 803 * @c: client session
808 * @type: type of request 804 * @type: type of request
809 * @uidata: user bffer that should be ued for zero copy read 805 * @uidata: destination for zero copy read
810 * @uodata: user buffer that shoud be user for zero copy write 806 * @uodata: source for zero copy write
811 * @inlen: read buffer size 807 * @inlen: read buffer size
812 * @olen: write buffer size 808 * @olen: write buffer size
813 * @hdrlen: reader header size, This is the size of response protocol data 809 * @hdrlen: reader header size, This is the size of response protocol data
@@ -816,9 +812,10 @@ reterr:
816 * Returns request structure (which client must free using p9_free_req) 812 * Returns request structure (which client must free using p9_free_req)
817 */ 813 */
818static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, 814static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
819 char *uidata, char *uodata, 815 struct iov_iter *uidata,
816 struct iov_iter *uodata,
820 int inlen, int olen, int in_hdrlen, 817 int inlen, int olen, int in_hdrlen,
821 int kern_buf, const char *fmt, ...) 818 const char *fmt, ...)
822{ 819{
823 va_list ap; 820 va_list ap;
824 int sigpending, err; 821 int sigpending, err;
@@ -841,12 +838,8 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
841 } else 838 } else
842 sigpending = 0; 839 sigpending = 0;
843 840
844 /* If we are called with KERNEL_DS force kern_buf */
845 if (segment_eq(get_fs(), KERNEL_DS))
846 kern_buf = 1;
847
848 err = c->trans_mod->zc_request(c, req, uidata, uodata, 841 err = c->trans_mod->zc_request(c, req, uidata, uodata,
849 inlen, olen, in_hdrlen, kern_buf); 842 inlen, olen, in_hdrlen);
850 if (err < 0) { 843 if (err < 0) {
851 if (err == -EIO) 844 if (err == -EIO)
852 c->status = Disconnected; 845 c->status = Disconnected;
@@ -876,7 +869,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
876 if (err < 0) 869 if (err < 0)
877 goto reterr; 870 goto reterr;
878 871
879 err = p9_check_zc_errors(c, req, uidata, in_hdrlen, kern_buf); 872 err = p9_check_zc_errors(c, req, uidata, in_hdrlen);
880 trace_9p_client_res(c, type, req->rc->tag, err); 873 trace_9p_client_res(c, type, req->rc->tag, err);
881 if (!err) 874 if (!err)
882 return req; 875 return req;
@@ -1545,11 +1538,24 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1545 u32 count) 1538 u32 count)
1546{ 1539{
1547 char *dataptr; 1540 char *dataptr;
1548 int kernel_buf = 0;
1549 struct p9_req_t *req; 1541 struct p9_req_t *req;
1550 struct p9_client *clnt; 1542 struct p9_client *clnt;
1551 int err, rsize, non_zc = 0; 1543 int err, rsize, non_zc = 0;
1552 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 }
1553 1559
1554 p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", 1560 p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n",
1555 fid->fid, (unsigned long long) offset, count); 1561 fid->fid, (unsigned long long) offset, count);
@@ -1565,18 +1571,12 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1565 1571
1566 /* Don't bother zerocopy for small IO (< 1024) */ 1572 /* Don't bother zerocopy for small IO (< 1024) */
1567 if (clnt->trans_mod->zc_request && rsize > 1024) { 1573 if (clnt->trans_mod->zc_request && rsize > 1024) {
1568 char *indata;
1569 if (data) {
1570 kernel_buf = 1;
1571 indata = data;
1572 } else
1573 indata = (__force char *)udata;
1574 /* 1574 /*
1575 * response header len is 11 1575 * response header len is 11
1576 * PDU Header(7) + IO Size (4) 1576 * PDU Header(7) + IO Size (4)
1577 */ 1577 */
1578 req = p9_client_zc_rpc(clnt, P9_TREAD, indata, NULL, rsize, 0, 1578 req = p9_client_zc_rpc(clnt, P9_TREAD, &to, NULL, rsize, 0,
1579 11, kernel_buf, "dqd", fid->fid, 1579 11, "dqd", fid->fid,
1580 offset, rsize); 1580 offset, rsize);
1581 } else { 1581 } else {
1582 non_zc = 1; 1582 non_zc = 1;
@@ -1596,16 +1596,9 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
1596 1596
1597 p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count); 1597 p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
1598 1598
1599 if (non_zc) { 1599 if (non_zc && copy_to_iter(dataptr, count, &to) != count) {
1600 if (data) { 1600 err = -EFAULT;
1601 memmove(data, dataptr, count); 1601 goto free_and_error;
1602 } else {
1603 err = copy_to_user(udata, dataptr, count);
1604 if (err) {
1605 err = -EFAULT;
1606 goto free_and_error;
1607 }
1608 }
1609 } 1602 }
1610 p9_free_req(clnt, req); 1603 p9_free_req(clnt, req);
1611 return count; 1604 return count;
@@ -1622,9 +1615,23 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1622 u64 offset, u32 count) 1615 u64 offset, u32 count)
1623{ 1616{
1624 int err, rsize; 1617 int err, rsize;
1625 int kernel_buf = 0;
1626 struct p9_client *clnt; 1618 struct p9_client *clnt;
1627 struct p9_req_t *req; 1619 struct p9_req_t *req;
1620 struct iov_iter from;
1621 union {
1622 struct kvec kv;
1623 struct iovec iov;
1624 } v;
1625
1626 if (data) {
1627 v.kv.iov_base = data;
1628 v.kv.iov_len = count;
1629 iov_iter_kvec(&from, ITER_KVEC | WRITE, &v.kv, 1, count);
1630 } else {
1631 v.iov.iov_base = udata;
1632 v.iov.iov_len = count;
1633 iov_iter_init(&from, WRITE, &v.iov, 1, count);
1634 }
1628 1635
1629 p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n", 1636 p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n",
1630 fid->fid, (unsigned long long) offset, count); 1637 fid->fid, (unsigned long long) offset, count);
@@ -1640,22 +1647,12 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
1640 1647
1641 /* Don't bother zerocopy for small IO (< 1024) */ 1648 /* Don't bother zerocopy for small IO (< 1024) */
1642 if (clnt->trans_mod->zc_request && rsize > 1024) { 1649 if (clnt->trans_mod->zc_request && rsize > 1024) {
1643 char *odata; 1650 req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, &from, 0, rsize,
1644 if (data) { 1651 P9_ZC_HDR_SZ, "dqd",
1645 kernel_buf = 1;
1646 odata = data;
1647 } else
1648 odata = (char *)udata;
1649 req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, odata, 0, rsize,
1650 P9_ZC_HDR_SZ, kernel_buf, "dqd",
1651 fid->fid, offset, rsize); 1652 fid->fid, offset, rsize);
1652 } else { 1653 } else {
1653 if (data) 1654 req = p9_client_rpc(clnt, P9_TWRITE, "dqV", fid->fid,
1654 req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, 1655 offset, rsize, &from);
1655 offset, rsize, data);
1656 else
1657 req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid,
1658 offset, rsize, udata);
1659 } 1656 }
1660 if (IS_ERR(req)) { 1657 if (IS_ERR(req)) {
1661 err = PTR_ERR(req); 1658 err = PTR_ERR(req);
@@ -2068,6 +2065,10 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
2068 struct p9_client *clnt; 2065 struct p9_client *clnt;
2069 struct p9_req_t *req; 2066 struct p9_req_t *req;
2070 char *dataptr; 2067 char *dataptr;
2068 struct kvec kv = {.iov_base = data, .iov_len = count};
2069 struct iov_iter to;
2070
2071 iov_iter_kvec(&to, READ | ITER_KVEC, &kv, 1, count);
2071 2072
2072 p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n", 2073 p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n",
2073 fid->fid, (unsigned long long) offset, count); 2074 fid->fid, (unsigned long long) offset, count);
@@ -2088,8 +2089,8 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
2088 * response header len is 11 2089 * response header len is 11
2089 * PDU Header(7) + IO Size (4) 2090 * PDU Header(7) + IO Size (4)
2090 */ 2091 */
2091 req = p9_client_zc_rpc(clnt, P9_TREADDIR, data, NULL, rsize, 0, 2092 req = p9_client_zc_rpc(clnt, P9_TREADDIR, &to, NULL, rsize, 0,
2092 11, 1, "dqd", fid->fid, offset, rsize); 2093 11, "dqd", fid->fid, offset, rsize);
2093 } else { 2094 } else {
2094 non_zc = 1; 2095 non_zc = 1;
2095 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, 2096 req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid,