From patchwork Mon Jul 31 22:57:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Stabellini X-Patchwork-Id: 9873283 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C21136037D for ; Mon, 31 Jul 2017 23:00:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C2BB3285FD for ; Mon, 31 Jul 2017 23:00:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B44AE2860D; Mon, 31 Jul 2017 23:00:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2A8BB285FD for ; Mon, 31 Jul 2017 23:00:17 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dcJdC-0004SX-ST; Mon, 31 Jul 2017 22:57:46 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dcJdA-0004Qa-TO for xen-devel@lists.xen.org; Mon, 31 Jul 2017 22:57:45 +0000 Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id 6B/FA-01994-8E5BF795; Mon, 31 Jul 2017 22:57:44 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrLLMWRWlGSWpSXmKPExsVybKJssu7zrfW RBvMeiVks+biYxYHR4+ju30wBjFGsmXlJ+RUJrBlnti1nKTihWzHn1A+WBsZzal2MXBxCAuuY JPZ8vMLYxcjBwSLgINF1KhPEZBSIkXjww7qLkRPIDJOYfHkJK4jNJmAo8ffJJjYQW0RAWuLa5 8uMIGOYBSYzSrx+94sZpFdYwF5i/2l7iImqEm/2MIOU8wq4Suz6/ZkFxJYQkJM4eWwy2EhOAT eJm5OaWCGuaWOU+Lx9JfMERt4FjAyrGNWLU4vKUot0DfWSijLTM0pyEzNzdA0NTPVyU4uLE9N TcxKTivWS83M3MQIDoZ6BgXEHY1Ov8yFGSQ4mJVFexZ76SCG+pPyUyozE4oz4otKc1OJDjDIc HEoSvIu3AOUEi1LTUyvSMnOAIQmTluDgURLhnb8RKM1bXJCYW5yZDpE6xWjMsWH1+i9MHK8m/ P/GJMSSl5+XKiXOOxdkkgBIaUZpHtwgWKxcYpSVEuZlZGBgEOIpSC3KzSxBlX/FKM7BqCQMMY UnM68Ebt8roFOYgE6RLK0FOaUkESEl1cCY8dDyipzjJMf3y8Re6D8Q7ItZtnjTOe25H5sWT/S 8wHFB+KNtanJ74ftsTuVZvOZLBG3+LW9jf6t/znpm2iYFjqPFXxev45UxmSOfk+A28VLvzDd7 1sxNil885/Vh/bMq2UHLoxnEs3MNAyz6dq/50BjkeCU/UEpJco/5grslydr/3h9gjr2txFKck WioxVxUnAgAN23+/JACAAA= X-Env-Sender: sstabellini@kernel.org X-Msg-Ref: server-5.tower-206.messagelabs.com!1501541861!103624996!1 X-Originating-IP: [198.145.29.99] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 9.4.25; banners=-,-,- X-VirusChecked: Checked Received: (qmail 15084 invoked from network); 31 Jul 2017 22:57:43 -0000 Received: from mail.kernel.org (HELO mail.kernel.org) (198.145.29.99) by server-5.tower-206.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 31 Jul 2017 22:57:43 -0000 Received: from localhost.localdomain (162-198-228-33.lightspeed.wlfrct.sbcglobal.net [162.198.228.33]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id D937122BDF; Mon, 31 Jul 2017 22:57:40 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D937122BDF From: Stefano Stabellini To: xen-devel@lists.xen.org Date: Mon, 31 Jul 2017 15:57:30 -0700 Message-Id: <1501541855-7354-8-git-send-email-sstabellini@kernel.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1501541855-7354-1-git-send-email-sstabellini@kernel.org> References: <1501541855-7354-1-git-send-email-sstabellini@kernel.org> Cc: jgross@suse.com, Stefano Stabellini , boris.ostrovsky@oracle.com, sstabellini@kernel.org, linux-kernel@vger.kernel.org Subject: [Xen-devel] [PATCH v3 08/13] xen/pvcalls: implement accept command X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Introduce a waitqueue to allow only one outstanding accept command at any given time and to implement polling on the passive socket. Introduce a flags field to keep track of in-flight accept and poll commands. Send PVCALLS_ACCEPT to the backend. Allocate a new active socket. Make sure that only one accept command is executed at any given time by setting PVCALLS_FLAG_ACCEPT_INFLIGHT and waiting on the inflight_accept_req waitqueue. Convert the new struct sock_mapping pointer into an uint64_t and use it as id for the new socket to pass to the backend. Check if the accept call is non-blocking: in that case after sending the ACCEPT command to the backend store the sock_mapping pointer of the new struct and the inflight req_id then return -EAGAIN (which will respond only when there is something to accept). Next time accept is called, we'll check if the ACCEPT command has been answered, if so we'll pick up where we left off, otherwise we return -EAGAIN again. Note that, differently from the other commands, we can use wait_event_interruptible (instead of wait_event) in the case of accept as we are able to track the req_id of the ACCEPT response that we are waiting. Signed-off-by: Stefano Stabellini CC: boris.ostrovsky@oracle.com CC: jgross@suse.com --- drivers/xen/pvcalls-front.c | 111 ++++++++++++++++++++++++++++++++++++++++++++ drivers/xen/pvcalls-front.h | 3 ++ 2 files changed, 114 insertions(+) diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c index b2757f5..f83b910 100644 --- a/drivers/xen/pvcalls-front.c +++ b/drivers/xen/pvcalls-front.c @@ -65,6 +65,16 @@ struct sock_mapping { #define PVCALLS_STATUS_BIND 1 #define PVCALLS_STATUS_LISTEN 2 uint8_t status; + /* + * Internal state-machine flags. + * Only one accept operation can be inflight for a socket. + * Only one poll operation can be inflight for a given socket. + */ +#define PVCALLS_FLAG_ACCEPT_INFLIGHT 0 + uint8_t flags; + uint32_t inflight_req_id; + struct sock_mapping *accept_map; + wait_queue_head_t inflight_accept_req; } passive; }; }; @@ -414,6 +424,107 @@ int pvcalls_front_listen(struct socket *sock, int backlog) return ret; } +int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags) +{ + struct pvcalls_bedata *bedata; + struct sock_mapping *map; + struct sock_mapping *map2 = NULL; + struct xen_pvcalls_request *req; + int notify, req_id, ret, evtchn, nonblock; + + if (!pvcalls_front_dev) + return -ENOTCONN; + bedata = dev_get_drvdata(&pvcalls_front_dev->dev); + + map = (struct sock_mapping *) READ_ONCE(sock->sk->sk_send_head); + if (!map) + return -ENOTSOCK; + + if (map->passive.status != PVCALLS_STATUS_LISTEN) + return -EINVAL; + + nonblock = flags & SOCK_NONBLOCK; + /* + * Backend only supports 1 inflight accept request, will return + * errors for the others + */ + if (test_and_set_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, + (void *)&map->passive.flags)) { + req_id = READ_ONCE(map->passive.inflight_req_id); + if (req_id != PVCALLS_INVALID_ID && + READ_ONCE(bedata->rsp[req_id].req_id) == req_id) + goto received; + if (nonblock) + return -EAGAIN; + if (wait_event_interruptible(map->passive.inflight_accept_req, + !test_and_set_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, + (void *)&map->passive.flags))) + return -EINTR; + } + + spin_lock(&bedata->pvcallss_lock); + ret = get_request(bedata, &req_id); + if (ret < 0) { + spin_unlock(&bedata->pvcallss_lock); + return ret; + } + map2 = kzalloc(sizeof(*map2), GFP_KERNEL); + if (map2 == NULL) + return -ENOMEM; + ret = create_active(map2, &evtchn); + if (ret < 0) { + kfree(map2); + return -ENOMEM; + } + list_add_tail(&map2->list, &bedata->socket_mappings); + + req = RING_GET_REQUEST(&bedata->ring, req_id); + req->req_id = req_id; + req->cmd = PVCALLS_ACCEPT; + req->u.accept.id = (uint64_t) map; + req->u.accept.ref = map2->active.ref; + req->u.accept.id_new = (uint64_t) map2; + req->u.accept.evtchn = evtchn; + map->passive.accept_map = map2; + + bedata->ring.req_prod_pvt++; + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&bedata->ring, notify); + spin_unlock(&bedata->pvcallss_lock); + if (notify) + notify_remote_via_irq(bedata->irq); + if (nonblock) { + WRITE_ONCE(map->passive.inflight_req_id, req_id); + return -EAGAIN; + } + + if (wait_event_interruptible(bedata->inflight_req, + READ_ONCE(bedata->rsp[req_id].req_id) == req_id)) + return -EINTR; + +received: + map2 = map->passive.accept_map; + map2->sock = newsock; + newsock->sk = kzalloc(sizeof(*newsock->sk), GFP_KERNEL); + if (!newsock->sk) { + WRITE_ONCE(bedata->rsp[req_id].req_id, PVCALLS_INVALID_ID); + WRITE_ONCE(map->passive.inflight_req_id, PVCALLS_INVALID_ID); + pvcalls_front_free_map(bedata, map2); + kfree(map2); + return -ENOMEM; + } + WRITE_ONCE(newsock->sk->sk_send_head, (void *)map2); + + clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, (void *)&map->passive.flags); + wake_up(&map->passive.inflight_accept_req); + + ret = bedata->rsp[req_id].ret; + /* read ret, then set this rsp slot to be reused */ + smp_mb(); + WRITE_ONCE(bedata->rsp[req_id].req_id, PVCALLS_INVALID_ID); + WRITE_ONCE(map->passive.inflight_req_id, PVCALLS_INVALID_ID); + return ret; +} + static const struct xenbus_device_id pvcalls_front_ids[] = { { "pvcalls" }, { "" } diff --git a/drivers/xen/pvcalls-front.h b/drivers/xen/pvcalls-front.h index aa8fe10..ab4f1da 100644 --- a/drivers/xen/pvcalls-front.h +++ b/drivers/xen/pvcalls-front.h @@ -10,5 +10,8 @@ int pvcalls_front_bind(struct socket *sock, struct sockaddr *addr, int addr_len); int pvcalls_front_listen(struct socket *sock, int backlog); +int pvcalls_front_accept(struct socket *sock, + struct socket *newsock, + int flags); #endif