9p: convert to advancing variant of iov_iter_get_pages_alloc()
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 10 Jun 2022 15:42:02 +0000 (11:42 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Tue, 9 Aug 2022 02:37:23 +0000 (22:37 -0400)
that one is somewhat clumsier than usual and needs serious testing.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
net/9p/client.c
net/9p/protocol.c
net/9p/trans_virtio.c

index d403085..cb43242 100644 (file)
@@ -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_req_t *req;
        int count = iov_iter_count(to);
-       int rsize, non_zc = 0;
+       int rsize, received, non_zc = 0;
        char *dataptr;
 
        *err = 0;
@@ -1520,36 +1520,40 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
        }
        if (IS_ERR(req)) {
                *err = PTR_ERR(req);
+               if (!non_zc)
+                       iov_iter_revert(to, count - iov_iter_count(to));
                return 0;
        }
 
        *err = p9pdu_readf(&req->rc, clnt->proto_version,
-                          "D", &count, &dataptr);
+                          "D", &received, &dataptr);
        if (*err) {
+               if (!non_zc)
+                       iov_iter_revert(to, count - iov_iter_count(to));
                trace_9p_protocol_dump(clnt, &req->rc);
                p9_tag_remove(clnt, req);
                return 0;
        }
-       if (rsize < count) {
-               pr_err("bogus RREAD count (%d > %d)\n", count, rsize);
-               count = rsize;
+       if (rsize < received) {
+               pr_err("bogus RREAD count (%d > %d)\n", received, rsize);
+               received = rsize;
        }
 
        p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
 
        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;
                        p9_tag_remove(clnt, req);
                        return n;
                }
        } else {
-               iov_iter_advance(to, count);
+               iov_iter_revert(to, count - received - iov_iter_count(to));
        }
        p9_tag_remove(clnt, req);
-       return count;
+       return received;
 }
 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)
        while (iov_iter_count(from)) {
                int count = iov_iter_count(from);
                int rsize = fid->iounit;
+               int written;
 
                if (!rsize || 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)
                                            offset, rsize, from);
                }
                if (IS_ERR(req)) {
+                       iov_iter_revert(from, count - iov_iter_count(from));
                        *err = PTR_ERR(req);
                        break;
                }
 
-               *err = p9pdu_readf(&req->rc, clnt->proto_version, "d", &count);
+               *err = p9pdu_readf(&req->rc, clnt->proto_version, "d", &written);
                if (*err) {
+                       iov_iter_revert(from, count - iov_iter_count(from));
                        trace_9p_protocol_dump(clnt, &req->rc);
                        p9_tag_remove(clnt, req);
                        break;
                }
-               if (rsize < count) {
-                       pr_err("bogus RWRITE count (%d > %d)\n", count, rsize);
-                       count = rsize;
+               if (rsize < written) {
+                       pr_err("bogus RWRITE count (%d > %d)\n", written, rsize);
+                       written = rsize;
                }
 
                p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
 
                p9_tag_remove(clnt, req);
-               iov_iter_advance(from, count);
-               total += count;
-               offset += count;
+               iov_iter_revert(from, count - written - iov_iter_count(from));
+               total += written;
+               offset += written;
        }
        return total;
 }
index 3754c33..83694c6 100644 (file)
@@ -63,9 +63,8 @@ static size_t
 pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t 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;
 
        pdu->size += len;
index 2a210c2..1977d33 100644 (file)
@@ -331,7 +331,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
                        if (err == -ERESTARTSYS)
                                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)
                        return n;
                *need_drop = 1;
@@ -373,6 +373,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
                                (*pages)[index] = kmap_to_page(p);
                        p += PAGE_SIZE;
                }
+               iov_iter_advance(data, len);
                return len;
        }
 }