2020-02-05 20:42:24

by L29Ah

[permalink] [raw]
Subject: [PATCH] 9pnet: allow making incomplete read requests

A user doesn't necessarily want to wait for all the requested data to
be available, since the waiting time for each request is unbounded.

The new method permits sending one read request at a time and getting
the response ASAP, allowing to use 9pnet with synthetic file systems
representing arbitrary data streams.

Signed-off-by: Sergey Alirzaev <[email protected]>
---
include/net/9p/client.h | 2 +
net/9p/client.c | 135 ++++++++++++++++++++++------------------
2 files changed, 76 insertions(+), 61 deletions(-)

diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index acc60d8a3b3b..f6c890e94f87 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -200,6 +200,8 @@ int p9_client_fsync(struct p9_fid *fid, int datasync);
int p9_client_remove(struct p9_fid *fid);
int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags);
int p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err);
+int p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
+ int *err);
int p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err);
int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset);
int p9dirent_read(struct p9_client *clnt, char *buf, int len,
diff --git a/net/9p/client.c b/net/9p/client.c
index 1d48afc7033c..240d7c05b282 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1549,82 +1549,95 @@ EXPORT_SYMBOL(p9_client_unlinkat);
int
p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
{
- struct p9_client *clnt = fid->clnt;
- struct p9_req_t *req;
int total = 0;
*err = 0;

+ while (iov_iter_count(to)) {
+ int count;
+
+ count = p9_client_read_once(fid, offset, to, err);
+ if (!count || *err)
+ break;
+ offset += count;
+ total += count;
+ }
+ return total;
+}
+EXPORT_SYMBOL(p9_client_read);
+
+int
+p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
+ int *err)
+{
+ struct p9_client *clnt = fid->clnt;
+ struct p9_req_t *req;
+ int count = iov_iter_count(to);
+ int rsize, non_zc = 0;
+ char *dataptr;
+
+ *err = 0;
p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n",
fid->fid, (unsigned long long) offset, (int)iov_iter_count(to));

- while (iov_iter_count(to)) {
- int count = iov_iter_count(to);
- int rsize, non_zc = 0;
- char *dataptr;
+ rsize = fid->iounit;
+ if (!rsize || rsize > clnt->msize - P9_IOHDRSZ)
+ rsize = clnt->msize - P9_IOHDRSZ;

- rsize = fid->iounit;
- if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
- rsize = clnt->msize - P9_IOHDRSZ;
+ if (count < rsize)
+ rsize = count;

- if (count < rsize)
- rsize = count;
+ /* Don't bother zerocopy for small IO (< 1024) */
+ if (clnt->trans_mod->zc_request && rsize > 1024) {
+ /* response header len is 11
+ * PDU Header(7) + IO Size (4)
+ */
+ req = p9_client_zc_rpc(clnt, P9_TREAD, to, NULL, rsize,
+ 0, 11, "dqd", fid->fid,
+ offset, rsize);
+ } else {
+ non_zc = 1;
+ req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
+ rsize);
+ }
+ if (IS_ERR(req)) {
+ *err = PTR_ERR(req);
+ return 0;
+ }

- /* Don't bother zerocopy for small IO (< 1024) */
- if (clnt->trans_mod->zc_request && rsize > 1024) {
- /*
- * response header len is 11
- * PDU Header(7) + IO Size (4)
- */
- req = p9_client_zc_rpc(clnt, P9_TREAD, to, NULL, rsize,
- 0, 11, "dqd", fid->fid,
- offset, rsize);
- } else {
- non_zc = 1;
- req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
- rsize);
- }
- if (IS_ERR(req)) {
- *err = PTR_ERR(req);
- break;
- }
+ *err = p9pdu_readf(&req->rc, clnt->proto_version,
+ "D", &count, &dataptr);
+ if (*err) {
+ 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;
+ }

- *err = p9pdu_readf(&req->rc, clnt->proto_version,
- "D", &count, &dataptr);
- if (*err) {
- trace_9p_protocol_dump(clnt, &req->rc);
- p9_tag_remove(clnt, req);
- break;
- }
- if (rsize < count) {
- pr_err("bogus RREAD count (%d > %d)\n", count, rsize);
- count = rsize;
- }
+ p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
+ if (!count) {
+ p9_tag_remove(clnt, req);
+ return 0;
+ }

- p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
- if (!count) {
- p9_tag_remove(clnt, req);
- break;
- }
+ if (non_zc) {
+ int n = copy_to_iter(dataptr, count, to);

- if (non_zc) {
- int n = copy_to_iter(dataptr, count, to);
- total += n;
- offset += n;
- if (n != count) {
- *err = -EFAULT;
- p9_tag_remove(clnt, req);
- break;
- }
- } else {
- iov_iter_advance(to, count);
- total += count;
- offset += count;
+ if (n != count) {
+ *err = -EFAULT;
+ p9_tag_remove(clnt, req);
+ return n;
}
- p9_tag_remove(clnt, req);
+ } else {
+ iov_iter_advance(to, count);
+ count;
}
- return total;
+ p9_tag_remove(clnt, req);
+ return count;
}
-EXPORT_SYMBOL(p9_client_read);
+EXPORT_SYMBOL(p9_client_read_once);

int
p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
--
2.25.0


2020-02-05 21:56:15

by Dominique Martinet

[permalink] [raw]
Subject: Re: [PATCH] 9pnet: allow making incomplete read requests

Sergey Alirzaev wrote on Wed, Feb 05, 2020:
> A user doesn't necessarily want to wait for all the requested data to
> be available, since the waiting time for each request is unbounded.
>
> The new method permits sending one read request at a time and getting
> the response ASAP, allowing to use 9pnet with synthetic file systems
> representing arbitrary data streams.

Much better, thanks!

> Signed-off-by: Sergey Alirzaev <[email protected]>
> [...]
> + if (n != count) {
> + *err = -EFAULT;
> + p9_tag_remove(clnt, req);
> + return n;
> }
> - p9_tag_remove(clnt, req);
> + } else {
> + iov_iter_advance(to, count);
> + count;

Any reason for this stray 'count;' statement?

If you're ok with this I'll just take patch without that line, don't
bother resubmitting.
Will take a fair amount of time to make it to linux-next though, test
setup needs some love and I want to run tests even if this should be
straightforward...

Thanks,
--
Dominique

2020-02-05 22:07:56

by L29Ah

[permalink] [raw]
Subject: Re: [PATCH] 9pnet: allow making incomplete read requests

On Wed, Feb 05, 2020 at 10:54:46PM +0100, Dominique Martinet wrote:
> > [...]
> > + if (n != count) {
> > + *err = -EFAULT;
> > + p9_tag_remove(clnt, req);
> > + return n;
> > }
> > - p9_tag_remove(clnt, req);
> > + } else {
> > + iov_iter_advance(to, count);
> > + count;
>
> Any reason for this stray 'count;' statement?
> If you're ok with this I'll just take patch without that line, don't
> bother resubmitting.

No reason, i've just accidentally left it.

> Will take a fair amount of time to make it to linux-next though, test
> setup needs some love and I want to run tests even if this should be
> straightforward...

Thanks!

--
() ascii ribbon campaign - against html mail
/\ http://arc.pasp.de/ - against proprietary attachments