Skip to content

Commit c66bb48

Browse files
committed
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: Dan Carpenter <error27@gmail.com> Link: https://lore.kernel.org/lkml/Y+JUIl64UDmdkboh@kadam/ Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org> Link: https://lore.kernel.org/r/20230403092711.15285-1-jgross@suse.com Signed-off-by: Juergen Gross <jgross@suse.com>
1 parent b2c042c commit c66bb48

File tree

1 file changed

+26
-20
lines changed

1 file changed

+26
-20
lines changed

drivers/xen/pvcalls-front.c

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -227,22 +227,30 @@ static irqreturn_t pvcalls_front_event_handler(int irq, void *dev_id)
227227

228228
static void free_active_ring(struct sock_mapping *map);
229229

230-
static void pvcalls_front_free_map(struct pvcalls_bedata *bedata,
231-
struct sock_mapping *map)
230+
static void pvcalls_front_destroy_active(struct pvcalls_bedata *bedata,
231+
struct sock_mapping *map)
232232
{
233233
int i;
234234

235235
unbind_from_irqhandler(map->active.irq, map);
236236

237-
spin_lock(&bedata->socket_lock);
238-
if (!list_empty(&map->list))
239-
list_del_init(&map->list);
240-
spin_unlock(&bedata->socket_lock);
237+
if (bedata) {
238+
spin_lock(&bedata->socket_lock);
239+
if (!list_empty(&map->list))
240+
list_del_init(&map->list);
241+
spin_unlock(&bedata->socket_lock);
242+
}
241243

242244
for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++)
243245
gnttab_end_foreign_access(map->active.ring->ref[i], NULL);
244246
gnttab_end_foreign_access(map->active.ref, NULL);
245247
free_active_ring(map);
248+
}
249+
250+
static void pvcalls_front_free_map(struct pvcalls_bedata *bedata,
251+
struct sock_mapping *map)
252+
{
253+
pvcalls_front_destroy_active(bedata, map);
246254

247255
kfree(map);
248256
}
@@ -433,19 +441,18 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr,
433441
pvcalls_exit_sock(sock);
434442
return ret;
435443
}
436-
437-
spin_lock(&bedata->socket_lock);
438-
ret = get_request(bedata, &req_id);
444+
ret = create_active(map, &evtchn);
439445
if (ret < 0) {
440-
spin_unlock(&bedata->socket_lock);
441446
free_active_ring(map);
442447
pvcalls_exit_sock(sock);
443448
return ret;
444449
}
445-
ret = create_active(map, &evtchn);
450+
451+
spin_lock(&bedata->socket_lock);
452+
ret = get_request(bedata, &req_id);
446453
if (ret < 0) {
447454
spin_unlock(&bedata->socket_lock);
448-
free_active_ring(map);
455+
pvcalls_front_destroy_active(NULL, map);
449456
pvcalls_exit_sock(sock);
450457
return ret;
451458
}
@@ -821,28 +828,27 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
821828
pvcalls_exit_sock(sock);
822829
return ret;
823830
}
824-
spin_lock(&bedata->socket_lock);
825-
ret = get_request(bedata, &req_id);
831+
ret = create_active(map2, &evtchn);
826832
if (ret < 0) {
827-
clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
828-
(void *)&map->passive.flags);
829-
spin_unlock(&bedata->socket_lock);
830833
free_active_ring(map2);
831834
kfree(map2);
835+
clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
836+
(void *)&map->passive.flags);
832837
pvcalls_exit_sock(sock);
833838
return ret;
834839
}
835840

836-
ret = create_active(map2, &evtchn);
841+
spin_lock(&bedata->socket_lock);
842+
ret = get_request(bedata, &req_id);
837843
if (ret < 0) {
838-
free_active_ring(map2);
839-
kfree(map2);
840844
clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
841845
(void *)&map->passive.flags);
842846
spin_unlock(&bedata->socket_lock);
847+
pvcalls_front_free_map(bedata, map2);
843848
pvcalls_exit_sock(sock);
844849
return ret;
845850
}
851+
846852
list_add_tail(&map2->list, &bedata->socket_mappings);
847853

848854
req = RING_GET_REQUEST(&bedata->ring, req_id);

0 commit comments

Comments
 (0)