Stop using softnet_lock (fix possible deadlock)
Using softnet_lock for mutual exclusion between lltable_free and arptimer was wrong and had an issue causing a deadlock between them; lltable_free waits arptimer completion by calling callout_halt with softnet_lock that is held in arptimer, however lltable_free also holds llentry's lock that is also held in arptimer so arptimer never obtain the lock and both never go forward eventually. We have to pass llentry's lock to callout_halt instead.
This commit is contained in:
parent
1c995f393c
commit
e4a5751875
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_llatbl.c,v 1.6 2015/09/30 07:12:32 ozaki-r Exp $ */
|
||||
/* $NetBSD: if_llatbl.c,v 1.7 2015/10/20 07:35:15 ozaki-r Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
|
||||
* Copyright (c) 2004-2008 Qing Li. All rights reserved.
|
||||
|
@ -364,7 +364,6 @@ lltable_free(struct lltable *llt)
|
|||
|
||||
lltable_unlink(llt);
|
||||
|
||||
mutex_enter(softnet_lock);
|
||||
LIST_INIT(&dchain);
|
||||
IF_AFDATA_WLOCK(llt->llt_ifp);
|
||||
/* Push all lles to @dchain */
|
||||
|
@ -373,7 +372,7 @@ lltable_free(struct lltable *llt)
|
|||
IF_AFDATA_WUNLOCK(llt->llt_ifp);
|
||||
|
||||
LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
|
||||
if (callout_halt(&lle->la_timer, softnet_lock))
|
||||
if (callout_halt(&lle->la_timer, &lle->lle_lock))
|
||||
LLE_REMREF(lle);
|
||||
#if defined(__NetBSD__)
|
||||
/* XXX should have callback? */
|
||||
|
@ -394,7 +393,6 @@ lltable_free(struct lltable *llt)
|
|||
#endif
|
||||
llentry_free(lle);
|
||||
}
|
||||
mutex_exit(softnet_lock);
|
||||
|
||||
llt->llt_free_tbl(llt);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_arp.c,v 1.189 2015/10/14 11:22:55 roy Exp $ */
|
||||
/* $NetBSD: if_arp.c,v 1.190 2015/10/20 07:35:15 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -68,7 +68,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.189 2015/10/14 11:22:55 roy Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.190 2015/10/20 07:35:15 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_ddb.h"
|
||||
|
@ -317,13 +317,11 @@ arptimer(void *arg)
|
|||
struct ifnet *ifp;
|
||||
struct rtentry *rt;
|
||||
|
||||
mutex_enter(softnet_lock);
|
||||
|
||||
if (lle == NULL)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
if (lle->la_flags & LLE_STATIC)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
LLE_WLOCK(lle);
|
||||
if (callout_pending(&lle->la_timer)) {
|
||||
|
@ -343,7 +341,7 @@ arptimer(void *arg)
|
|||
* by arpresolve() below.
|
||||
*/
|
||||
LLE_WUNLOCK(lle);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
ifp = lle->lle_tbl->llt_ifp;
|
||||
rt = lle->la_rt;
|
||||
|
@ -374,9 +372,6 @@ arptimer(void *arg)
|
|||
}
|
||||
|
||||
IF_AFDATA_UNLOCK(ifp);
|
||||
|
||||
out:
|
||||
mutex_exit(softnet_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue