Commit c66bb48e authored by Juergen Gross's avatar Juergen Gross

xen/pvcalls: don't call bind_evtchn_to_irqhandler() under lock

bind_evtchn_to_irqhandler() shouldn't be called under spinlock, as it
can sleep.

This requires to move the calls of create_active() out of the locked
regions. This is no problem, as the worst which could happen would be
a spurious call of the interrupt handler, causing a spurious wake_up().
Reported-by: default avatarDan Carpenter <error27@gmail.com>
Link: https://lore.kernel.org/lkml/Y+JUIl64UDmdkboh@kadam/Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Reviewed-by: default avatarOleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
Reviewed-by: default avatarStefano Stabellini <sstabellini@kernel.org>
Link: https://lore.kernel.org/r/20230403092711.15285-1-jgross@suse.comSigned-off-by: default avatarJuergen Gross <jgross@suse.com>
parent b2c042cc
...@@ -227,22 +227,30 @@ static irqreturn_t pvcalls_front_event_handler(int irq, void *dev_id) ...@@ -227,22 +227,30 @@ static irqreturn_t pvcalls_front_event_handler(int irq, void *dev_id)
static void free_active_ring(struct sock_mapping *map); static void free_active_ring(struct sock_mapping *map);
static void pvcalls_front_free_map(struct pvcalls_bedata *bedata, static void pvcalls_front_destroy_active(struct pvcalls_bedata *bedata,
struct sock_mapping *map) struct sock_mapping *map)
{ {
int i; int i;
unbind_from_irqhandler(map->active.irq, map); unbind_from_irqhandler(map->active.irq, map);
spin_lock(&bedata->socket_lock); if (bedata) {
if (!list_empty(&map->list)) spin_lock(&bedata->socket_lock);
list_del_init(&map->list); if (!list_empty(&map->list))
spin_unlock(&bedata->socket_lock); list_del_init(&map->list);
spin_unlock(&bedata->socket_lock);
}
for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++) for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++)
gnttab_end_foreign_access(map->active.ring->ref[i], NULL); gnttab_end_foreign_access(map->active.ring->ref[i], NULL);
gnttab_end_foreign_access(map->active.ref, NULL); gnttab_end_foreign_access(map->active.ref, NULL);
free_active_ring(map); free_active_ring(map);
}
static void pvcalls_front_free_map(struct pvcalls_bedata *bedata,
struct sock_mapping *map)
{
pvcalls_front_destroy_active(bedata, map);
kfree(map); kfree(map);
} }
...@@ -433,19 +441,18 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr, ...@@ -433,19 +441,18 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr,
pvcalls_exit_sock(sock); pvcalls_exit_sock(sock);
return ret; return ret;
} }
ret = create_active(map, &evtchn);
spin_lock(&bedata->socket_lock);
ret = get_request(bedata, &req_id);
if (ret < 0) { if (ret < 0) {
spin_unlock(&bedata->socket_lock);
free_active_ring(map); free_active_ring(map);
pvcalls_exit_sock(sock); pvcalls_exit_sock(sock);
return ret; return ret;
} }
ret = create_active(map, &evtchn);
spin_lock(&bedata->socket_lock);
ret = get_request(bedata, &req_id);
if (ret < 0) { if (ret < 0) {
spin_unlock(&bedata->socket_lock); spin_unlock(&bedata->socket_lock);
free_active_ring(map); pvcalls_front_destroy_active(NULL, map);
pvcalls_exit_sock(sock); pvcalls_exit_sock(sock);
return ret; return ret;
} }
...@@ -821,28 +828,27 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -821,28 +828,27 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
pvcalls_exit_sock(sock); pvcalls_exit_sock(sock);
return ret; return ret;
} }
spin_lock(&bedata->socket_lock); ret = create_active(map2, &evtchn);
ret = get_request(bedata, &req_id);
if (ret < 0) { if (ret < 0) {
clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
(void *)&map->passive.flags);
spin_unlock(&bedata->socket_lock);
free_active_ring(map2); free_active_ring(map2);
kfree(map2); kfree(map2);
clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
(void *)&map->passive.flags);
pvcalls_exit_sock(sock); pvcalls_exit_sock(sock);
return ret; return ret;
} }
ret = create_active(map2, &evtchn); spin_lock(&bedata->socket_lock);
ret = get_request(bedata, &req_id);
if (ret < 0) { if (ret < 0) {
free_active_ring(map2);
kfree(map2);
clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
(void *)&map->passive.flags); (void *)&map->passive.flags);
spin_unlock(&bedata->socket_lock); spin_unlock(&bedata->socket_lock);
pvcalls_front_free_map(bedata, map2);
pvcalls_exit_sock(sock); pvcalls_exit_sock(sock);
return ret; return ret;
} }
list_add_tail(&map2->list, &bedata->socket_mappings); list_add_tail(&map2->list, &bedata->socket_mappings);
req = RING_GET_REQUEST(&bedata->ring, req_id); req = RING_GET_REQUEST(&bedata->ring, req_id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment