Skip to content

Commit d28c756

Browse files
jynnantonixDominique Martinet
authored andcommitted
9p/net: Fix zero-copy path in the 9p virtio transport
The zero-copy optimization when reading or writing large chunks of data is quite useful. However, the 9p messages created through the zero-copy write path have an incorrect message size: it should be the size of the header + size of the data being written but instead it's just the size of the header. This only works if the server ignores the size field of the message and otherwise breaks the framing of the protocol. Fix this by re-writing the message size field with the correct value. Tested by running `dd if=/dev/zero of=out bs=4k count=1` inside a virtio-9p mount. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Chirantan Ekbote <[email protected]> Reviewed-by: Greg Kurz <[email protected]> Tested-by: Greg Kurz <[email protected]> Cc: Dylan Reid <[email protected]> Cc: Guenter Roeck <[email protected]> Cc: [email protected] Signed-off-by: Dominique Martinet <[email protected]>
1 parent 2557d0c commit d28c756

File tree

1 file changed

+7
-0
lines changed

1 file changed

+7
-0
lines changed

net/9p/trans_virtio.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
406406
p9_debug(P9_DEBUG_TRANS, "virtio request\n");
407407

408408
if (uodata) {
409+
__le32 sz;
409410
int n = p9_get_mapped_pages(chan, &out_pages, uodata,
410411
outlen, &offs, &need_drop);
411412
if (n < 0)
@@ -416,6 +417,12 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
416417
memcpy(&req->tc->sdata[req->tc->size - 4], &v, 4);
417418
outlen = n;
418419
}
420+
/* The size field of the message must include the length of the
421+
* header and the length of the data. We didn't actually know
422+
* the length of the data until this point so add it in now.
423+
*/
424+
sz = cpu_to_le32(req->tc->size + outlen);
425+
memcpy(&req->tc->sdata[0], &sz, sizeof(sz));
419426
} else if (uidata) {
420427
int n = p9_get_mapped_pages(chan, &in_pages, uidata,
421428
inlen, &offs, &need_drop);

0 commit comments

Comments
 (0)