[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] xen/pvcalls: don't call bind_evtchn_to_irqhandler() under lock





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 <error27@xxxxxxxxx>
Link: https://lore.kernel.org/lkml/Y+JUIl64UDmdkboh@kadam/
Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
  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?


-               free_active_ring(map2);
-               kfree(map2);
                pvcalls_exit_sock(sock);
                return ret;
        }
- ret = create_active(map2, &evtchn);
+       spin_lock(&bedata->socket_lock);
+       ret = get_request(bedata, &req_id);
        if (ret < 0) {
-               free_active_ring(map2);
-               kfree(map2);
                clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
                          (void *)&map->passive.flags);
                spin_unlock(&bedata->socket_lock);
+               pvcalls_front_free_map(bedata, map2);
                pvcalls_exit_sock(sock);
                return ret;
        }
+
        list_add_tail(&map2->list, &bedata->socket_mappings);
req = RING_GET_REQUEST(&bedata->ring, req_id);



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.