linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dominique Martinet <dominique.martinet@cea.fr>
To: Stefano Stabellini <sstabellini@kernel.org>
Cc: v9fs-developer@lists.sourceforge.net, ericvh@gmail.com,
	rminnich@sandia.gov, linux-kernel@vger.kernel.org,
	lucho@ionkov.net
Subject: Re: [V9fs-developer] [PATCH 4/5] 9p: introduce async read requests
Date: Fri, 9 Dec 2016 08:27:17 +0100	[thread overview]
Message-ID: <20161209072717.GD18158@nautica> (raw)
In-Reply-To: <1481230746-16741-4-git-send-email-sstabellini@kernel.org>

Stefano Stabellini wrote on Thu, Dec 08, 2016:
> If the read is an async operation, send a 9p request and return
> EIOCBQUEUED. Do not wait for completion.
> 
> Complete the read operation from a callback instead.
> 
> Signed-off-by: Stefano Stabellini <sstabellini@kernel.org>
> ---
>  net/9p/client.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 86 insertions(+), 2 deletions(-)
> 
> diff --git a/net/9p/client.c b/net/9p/client.c
> index eb589ef..f9f09db 100644
> --- a/net/9p/client.c
> +++ b/net/9p/client.c
> @@ -28,6 +28,7 @@
>  #include <linux/module.h>
>  #include <linux/errno.h>
>  #include <linux/fs.h>
> +#include <linux/pagemap.h>
>  #include <linux/poll.h>
>  #include <linux/idr.h>
>  #include <linux/mutex.h>
> @@ -1554,13 +1555,68 @@ int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags)
>  }
>  EXPORT_SYMBOL(p9_client_unlinkat);
>  
> +static void
> +p9_client_read_complete(struct p9_client *clnt, struct p9_req_t *req, int status)
> +{
> +	int err, count, n, i, total = 0;
> +	char *dataptr, *to;
> +
> +	if (req->status == REQ_STATUS_ERROR) {
> +		p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
> +		err = req->t_err;
> +		goto out;
> +	}
> +	err = p9_check_errors(clnt, req);
> +	if (err)
> +		goto out;
> +
> +	err = p9pdu_readf(req->rc, clnt->proto_version,
> +			"D", &count, &dataptr);
> +	if (err) {
> +		trace_9p_protocol_dump(clnt, req->rc);
> +		goto out;
> +	}
> +	if (!count) {
> +		p9_debug(P9_DEBUG_ERROR, "count=%d\n", count);
> +		err = 0;
> +		goto out;
> +	}
> +
> +	p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
> +	if (count > req->rsize)
> +		count = req->rsize;
> +
> +	for (i = 0; i < ((req->rsize + PAGE_SIZE - 1) / PAGE_SIZE); i++) {
> +		to = kmap(req->pagevec[i]);
> +		to += req->offset;
> +		n = PAGE_SIZE - req->offset;
> +		if (n > count)
> +			n = count;
> +		memcpy(to, dataptr, n);
> +		kunmap(req->pagevec[i]);
> +		req->offset = 0;
> +		count -= n;
> +		total += n;
> +	}
> +
> +	err = total;
> +	req->kiocb->ki_pos += total;
> +
> +out:
> +	req->kiocb->ki_complete(req->kiocb, err, 0);
> +
> +	release_pages(req->pagevec, (req->rsize + PAGE_SIZE - 1) / PAGE_SIZE, false);
> +	kvfree(req->pagevec);
> +	p9_free_req(clnt, req);
> +}
> +
>  int
>  p9_client_read(struct p9_fid *fid, struct kiocb *iocb, u64 offset,
>  				struct iov_iter *to, int *err)
>  {
>  	struct p9_client *clnt = fid->clnt;
>  	struct p9_req_t *req;
> -	int total = 0;
> +	int total = 0, i;
>  	*err = 0;
>  
>  	p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n",
> @@ -1587,10 +1643,38 @@ int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags)
>  			req = p9_client_zc_rpc(clnt, P9_TREAD, to, NULL, rsize,
>  					       0, 11, "dqd", fid->fid,
>  					       offset, rsize);
> -		} else {
> +		/* sync request */
> +		} else if(iocb == NULL || is_sync_kiocb(iocb)) {
>  			non_zc = 1;
>  			req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
>  					    rsize);
> +		/* async request */
> +		} else {

I'm not too familiar with iocb/how async IOs should work, but a logic
question just to make sure that has been thought out:
We prefer zc here to async, even if zc can be slow?

Ideally at some point zc and async aren't exclusive so we'll have async
zc and async normal, but for now I'd say async comes before zc - yes
there will be an extra copy in memory, but it will be done
asynchronously.
Was it intentional to prefer zc here?

> +			req = p9_client_get_req(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize);
> +			if (IS_ERR(req)) {
> +				*err = PTR_ERR(req);
> +				break;
> +			}
> +			req->rsize = iov_iter_get_pages_alloc(to, &req->pagevec, 
> +					(size_t)rsize, &req->offset);
> +			req->kiocb = iocb;
> +			for (i = 0; i < req->rsize; i += PAGE_SIZE)
> +				page_cache_get_speculative(req->pagevec[i/PAGE_SIZE]);
> +			req->callback = p9_client_read_complete;
> +
> +			*err = clnt->trans_mod->request(clnt, req);
> +			if (*err < 0) {
> +				clnt->status = Disconnected;
> +				release_pages(req->pagevec,
> +						(req->rsize + PAGE_SIZE - 1) / PAGE_SIZE,
> +						true);
> +				kvfree(req->pagevec);
> +				p9_free_req(clnt, req);
> +				break;
> +			}
> +
> +			*err = -EIOCBQUEUED;
> +			break;

(Just a note to myself (or anyone who wants to do this) that a couple of
places only look at err if size written is 0... They should check if err
has been set)

>  		}
>  		if (IS_ERR(req)) {
>  			*err = PTR_ERR(req);

  reply	other threads:[~2016-12-09  7:27 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-12-08 20:58 [PATCH 0/5] async requests support for 9pfs Stefano Stabellini
2016-12-08 20:59 ` [PATCH 1/5] 9p: add iocb parameter to p9_client_read and p9_client_write Stefano Stabellini
2016-12-08 20:59   ` [PATCH 2/5] 9p: store req details and callback in struct p9_req_t Stefano Stabellini
2016-12-09  7:18     ` [V9fs-developer] " Dominique Martinet
2016-12-09 23:24       ` Stefano Stabellini
2016-12-08 20:59   ` [PATCH 3/5] 9p: introduce p9_client_get_req Stefano Stabellini
2016-12-08 20:59   ` [PATCH 4/5] 9p: introduce async read requests Stefano Stabellini
2016-12-09  7:27     ` Dominique Martinet [this message]
2016-12-09 22:22       ` [V9fs-developer] " Stefano Stabellini
2016-12-10  1:50     ` Al Viro
2016-12-13  1:15       ` Stefano Stabellini
2016-12-13 14:29         ` Latchesar Ionkov
2016-12-08 20:59   ` [PATCH 5/5] 9p: introduce async write requests Stefano Stabellini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161209072717.GD18158@nautica \
    --to=dominique.martinet@cea.fr \
    --cc=ericvh@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lucho@ionkov.net \
    --cc=rminnich@sandia.gov \
    --cc=sstabellini@kernel.org \
    --cc=v9fs-developer@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).