[libvirt] [PATCH] nwfilter: fix lock order deadlock
Laine Stump
laine at laine.org
Wed Apr 20 16:04:05 UTC 2016
Stefan - since you wrote the nwfilter driver, perhaps you could take a
look at this? (assuming that it hasn't all paged out of your brain by
now :-)
On 04/09/2016 12:14 PM, Maxim Nestratov wrote:
> Below is backtraces of two deadlocked threads:
>
> thread #1:
> virDomainConfVMNWFilterTeardown
> virNWFilterTeardownFilter
> lock updateMutex <------------
> _virNWFilterTeardownFilter
> try to lock interface <----------
>
> thread #2:
> learnIPAddressThread
> lock interface <-------
> virNWFilterInstantiateFilterLate
> try to lock updateMutex <----------
>
> The problem is fixed by unlocking interface before calling
> virNWFilterInstantiateFilterLate to avoid updateMutex and interface ordering
> deadlocks. Otherwise we are going to instantiate the filter while holding
> interface lock, which will try to lock updateMutex, and if some other thread
> instantiating a filter in parallel is holding updateMutex and is trying to
> lock interface, both will deadlock.
> Also it is safe to unlock interface before virNWFilterInstantiateFilterLate
> because learnIPAddressThread stopped capturing packets and applied necessary
> rules on the interface, while instantiating a new filter doesn't require a
> locked interface.
>
> Signed-off-by: Maxim Nestratov <mnestratov at virtuozzo.com>
> ---
> src/nwfilter/nwfilter_learnipaddr.c | 12 +++++++++++-
> 1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c
> index 1adbadb..cfd92d9 100644
> --- a/src/nwfilter/nwfilter_learnipaddr.c
> +++ b/src/nwfilter/nwfilter_learnipaddr.c
> @@ -611,6 +611,16 @@ learnIPAddressThread(void *arg)
> sa.data.inet4.sin_addr.s_addr = vmaddr;
> char *inetaddr;
>
> + /* It is necessary to unlock interface here to avoid updateMutex and
> + * interface ordering deadlocks. Otherwise we are going to
> + * instantiate the filter, which will try to lock updateMutex, and
> + * some other thread instantiating a filter in parallel is holding
> + * updateMutex and is trying to lock interface, both will deadlock.
> + * Also it is safe to unlock interface here because we stopped
> + * capturing and applied necessary rules on the interface, while
> + * instantiating a new filter doesn't require a locked interface.*/
> + virNWFilterUnlockIface(req->ifname);
> +
> if ((inetaddr = virSocketAddrFormat(&sa)) != NULL) {
> if (virNWFilterIPAddrMapAddIPAddr(req->ifname, inetaddr) < 0) {
> VIR_ERROR(_("Failed to add IP address %s to IP address "
> @@ -636,11 +646,11 @@ learnIPAddressThread(void *arg)
> req->ifname, req->ifindex);
>
> techdriver->applyDropAllRules(req->ifname);
> + virNWFilterUnlockIface(req->ifname);
> }
>
> VIR_DEBUG("pcap thread terminating for interface %s", req->ifname);
>
> - virNWFilterUnlockIface(req->ifname);
>
> err_no_lock:
> virNWFilterDeregisterLearnReq(req->ifindex);
More information about the libvir-list
mailing list