linux/net/9p
Al Viro f615625a44 9p: handling Rerror without copy_from_iter_full()
p9_client_zc_rpc()/p9_check_zc_errors() are playing fast
and loose with copy_from_iter_full().

	Reading from file is done by sending Tread request.  Response
consists of fixed-sized header (including the amount of data actually
read) followed by the data itself.

	For zero-copy case we arrange the things so that the first
11 bytes of reply go into the fixed-sized buffer, with the rest going
straight into the pages we want to read into.

	What makes the things inconvenient is that sglist describing
what should go where has to be set *before* the reply arrives.  As
the result, if reply is an error, the things get interesting.  On success
we get
	size[4] Rread tag[2] count[4] data[count]
For error layout varies depending upon the protocol variant -
in original 9P and 9P2000 it's
	size[4] Rerror tag[2] len[2] error[len]
in 9P2000.U
	size[4] Rerror tag[2] len[2] error[len] errno[4]
in 9P2000.L
	size[4] Rlerror tag[2] errno[4]

	The last case is nice and simple - we have an 11-byte response
that fits into the fixed-sized buffer we hoped to get an Rread into.
In other two, though, we get a variable-length string spill into the
pages we'd prepared for the data to be read.

	Had that been in fixed-sized buffer (which is actually 4K),
we would've dealt with that the same way we handle non-zerocopy case.
However, for zerocopy it doesn't end up there, so we need to copy it
from those pages.

	The trouble is, by the time we get around to that, the
references to pages in question are already dropped.  As the result,
p9_zc_check_errors() tries to get the data using copy_from_iter_full().
Unfortunately, the iov_iter it's trying to read from might *NOT* be
capable of that.  It is, after all, a data destination, not data source.
In particular, if it's an ITER_PIPE one, copy_from_iter_full() will
simply fail.

	In ->zc_request() itself we do have those pages and dealing with
the problem in there would be a simple matter of memcpy_from_page()
into the fixed-sized buffer.  Moreover, it isn't hard to recognize
the (rare) case when such copying is needed.  That way we get rid of
p9_zc_check_errors() entirely - p9_check_errors() can be used instead
both for zero-copy and non-zero-copy cases.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2022-06-09 10:01:34 -04:00
..
client.c 9p: handling Rerror without copy_from_iter_full() 2022-06-09 10:01:34 -04:00
error.c 9p: fix a bunch of checkpatch warnings 2021-11-04 21:04:25 +09:00
Kconfig 9p/trans_fd: split into dedicated module 2022-01-10 09:58:30 +09:00
Makefile 9p/trans_fd: split into dedicated module 2022-01-10 09:58:30 +09:00
mod.c net/p9: load default transports 2022-01-10 10:00:09 +09:00
protocol.c 9p: fix a bunch of checkpatch warnings 2021-11-04 21:04:25 +09:00
protocol.h 9p: fix a bunch of checkpatch warnings 2021-11-04 21:04:25 +09:00
trans_common.c 9p: fix file headers 2021-11-03 17:45:04 +09:00
trans_common.h 9p: fix a bunch of checkpatch warnings 2021-11-04 21:04:25 +09:00
trans_fd.c 9p/trans_fd: split into dedicated module 2022-01-10 09:58:30 +09:00
trans_rdma.c 9p: fix file headers 2021-11-03 17:45:04 +09:00
trans_virtio.c 9p: handling Rerror without copy_from_iter_full() 2022-06-09 10:01:34 -04:00
trans_xen.c xen: switch gnttab_end_foreign_access() to take a struct page pointer 2022-05-27 11:05:29 +02:00