Re: [PATCH v5 12/13] xen/pvcalls: implement release command
From: Boris Ostrovsky
Date: Tue Oct 24 2017 - 10:16:55 EST
(I just noticed that I missed this patch, sorry)
On 10/06/2017 08:30 PM, Stefano Stabellini wrote:
> Send PVCALLS_RELEASE to the backend and wait for a reply. Take both
> in_mutex and out_mutex to avoid concurrent accesses. Then, free the
> socket.
>
> For passive sockets, check whether we have already pre-allocated an
> active socket for the purpose of being accepted. If so, free that as
> well.
>
> Signed-off-by: Stefano Stabellini <stefano@xxxxxxxxxxx>
> CC: boris.ostrovsky@xxxxxxxxxx
> CC: jgross@xxxxxxxx
> ---
> drivers/xen/pvcalls-front.c | 98 +++++++++++++++++++++++++++++++++++++++++++++
> drivers/xen/pvcalls-front.h | 1 +
> 2 files changed, 99 insertions(+)
>
> diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c
> index aca2b32..9beb34d 100644
> --- a/drivers/xen/pvcalls-front.c
> +++ b/drivers/xen/pvcalls-front.c
> @@ -200,6 +200,19 @@ static irqreturn_t pvcalls_front_event_handler(int irq, void *dev_id)
> static void pvcalls_front_free_map(struct pvcalls_bedata *bedata,
> struct sock_mapping *map)
> {
> + int i;
> +
> + unbind_from_irqhandler(map->active.irq, map);
> +
> + spin_lock(&bedata->socket_lock);
> + if (!list_empty(&map->list))
> + list_del_init(&map->list);
As with patch 2, do you need to init this? In fact, do you need to do
anything with the list? We are about to free the map (and so maybe bring
'kfree(map)" inside here, btw?)
And what does it mean if the list is not empty? Is it OK to free the map?
> + spin_unlock(&bedata->socket_lock);
> +
> + for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++)
> + gnttab_end_foreign_access(map->active.ring->ref[i], 0, 0);
> + gnttab_end_foreign_access(map->active.ref, 0, 0);
> + free_page((unsigned long)map->active.ring);
> }
>
> static irqreturn_t pvcalls_front_conn_handler(int irq, void *sock_map)
> @@ -968,6 +981,91 @@ unsigned int pvcalls_front_poll(struct file *file, struct socket *sock,
> return ret;
> }
>
> +
> + if (map->active_socket) {
> + /*
> + * Set in_error and wake up inflight_conn_req to force
> + * recvmsg waiters to exit.
> + */
> + map->active.ring->in_error = -EBADF;
> + wake_up_interruptible(&map->active.inflight_conn_req);
> +
> + /*
> + * Wait until there are no more waiters on the mutexes.
> + * We know that no new waiters can be added because sk_send_head
> + * is set to NULL -- we only need to wait for the existing
> + * waiters to return.
> + */
> + while (!mutex_trylock(&map->active.in_mutex) ||
> + !mutex_trylock(&map->active.out_mutex))
> + cpu_relax();
> +
> + pvcalls_front_free_map(bedata, map);
> + kfree(map);
> + } else {
> + spin_lock(&bedata->socket_lock);
> + if (READ_ONCE(map->passive.inflight_req_id) !=
> + PVCALLS_INVALID_ID) {
> + pvcalls_front_free_map(bedata,
pvcalls_front_free_map will try to grab bedata->socket_lock, which we are already holding.
> + map->passive.accept_map);
> + kfree(map->passive.accept_map);
> + }
> + list_del_init(&map->list);
Again, no init?
-boris
> + kfree(map);
> + spin_unlock(&bedata->socket_lock);
> + }
> + WRITE_ONCE(bedata->rsp[req_id].req_id, PVCALLS_INVALID_ID);
>