On 28.03.23 12:34, Oleksandr Tyshchenko wrote: > > > On 28.03.23 12:39, Juergen Gross wrote: > > Hello Juergen > > >> 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: Dan Carpenter >> Link: https://lore.kernel.org/lkml/Y+JUIl64UDmdkboh@kadam/ >> Signed-off-by: Juergen Gross >> --- >>   drivers/xen/pvcalls-front.c | 46 ++++++++++++++++++++++--------------- >>   1 file changed, 27 insertions(+), 19 deletions(-) >> >> diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c >> index d5d589bda243..6e5d712e3115 100644 >> --- a/drivers/xen/pvcalls-front.c >> +++ b/drivers/xen/pvcalls-front.c >> @@ -227,22 +227,31 @@ static irqreturn_t pvcalls_front_event_handler(int irq, >> void *dev_id) >>   static void free_active_ring(struct sock_mapping *map); >> -static void pvcalls_front_free_map(struct pvcalls_bedata *bedata, >> -                   struct sock_mapping *map) >> +static void pvcalls_front_destroy_active(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); >> -    spin_unlock(&bedata->socket_lock); >> +    if (bedata) { >> +        spin_lock(&bedata->socket_lock); >> +        if (!list_empty(&map->list)) >> +            list_del_init(&map->list); >> +        spin_unlock(&bedata->socket_lock); >> +    } >>       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.ref, NULL); >> + >>       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); >>   } >> @@ -433,19 +442,18 @@ int pvcalls_front_connect(struct socket *sock, struct >> sockaddr *addr, >>           pvcalls_exit_sock(sock); >>           return ret; >>       } >> - >> -    spin_lock(&bedata->socket_lock); >> -    ret = get_request(bedata, &req_id); >> +    ret = create_active(map, &evtchn); >>       if (ret < 0) { >> -        spin_unlock(&bedata->socket_lock); >>           free_active_ring(map); >>           pvcalls_exit_sock(sock); >>           return ret; >>       } >> -    ret = create_active(map, &evtchn); >> + >> +    spin_lock(&bedata->socket_lock); >> +    ret = get_request(bedata, &req_id); >>       if (ret < 0) { >>           spin_unlock(&bedata->socket_lock); >> -        free_active_ring(map); >> +        pvcalls_front_destroy_active(NULL, map); >>           pvcalls_exit_sock(sock); >>           return ret; >>       } >> @@ -821,28 +829,28 @@ int pvcalls_front_accept(struct socket *sock, struct >> socket *newsock, int flags) >>           pvcalls_exit_sock(sock); >>           return ret; >>       } >> -    spin_lock(&bedata->socket_lock); >> -    ret = get_request(bedata, &req_id); >> +    ret = create_active(map2, &evtchn); >>       if (ret < 0) { >> +        free_active_ring(map2); >> +        kfree(map2); >>           clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, >>                 (void *)&map->passive.flags); >>           spin_unlock(&bedata->socket_lock); > > > Looks like we also need to remove spin_unlock() above, correct? Thanks for catching! Juergen