summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Asselstine <mark.asselstine@windriver.com>2018-09-26 15:12:16 -0400
committerBruce Ashfield <bruce.ashfield@windriver.com>2018-09-30 21:31:14 -0400
commit6e3fb05e2a67f0a21971357b2459ac59e03e352e (patch)
tree3e1def1899821ae005d8e79cad1c2aa7fadbe34e
parentb3619dec91e171cfdd6eb0636708b45e8d3f2e93 (diff)
downloadmeta-virtualization-6e3fb05e2a67f0a21971357b2459ac59e03e352e.tar.gz
libvirt: backport LXC AB / BA deadlock fix
This fix will most likely be part of libvirt 4.8.0 but since we took the time to investigate and fix this issue we are including it now to prevent others from hitting this issue. Signed-off-by: Mark Asselstine <mark.asselstine@windriver.com> Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
-rw-r--r--recipes-extended/libvirt/libvirt/lxc_monitor-Avoid-AB-BA-lock-race.patch106
-rw-r--r--recipes-extended/libvirt/libvirt_4.7.0.bb1
2 files changed, 107 insertions, 0 deletions
diff --git a/recipes-extended/libvirt/libvirt/lxc_monitor-Avoid-AB-BA-lock-race.patch b/recipes-extended/libvirt/libvirt/lxc_monitor-Avoid-AB-BA-lock-race.patch
new file mode 100644
index 00000000..fc3880fb
--- /dev/null
+++ b/recipes-extended/libvirt/libvirt/lxc_monitor-Avoid-AB-BA-lock-race.patch
@@ -0,0 +1,106 @@
1From 7882c6eca53fe9abe253497a50f6c5ae062176d3 Mon Sep 17 00:00:00 2001
2From: Mark Asselstine <mark.asselstine@windriver.com>
3Date: Mon, 24 Sep 2018 11:11:35 -0400
4Subject: [PATCH] lxc_monitor: Avoid AB / BA lock race
5
6A deadlock situation can occur when autostarting a LXC domain 'guest'
7due to two threads attempting to take opposing locks while holding
8opposing locks (AB BA problem). Thread A takes and holds the 'vm' lock
9while attempting to take the 'client' lock, meanwhile, thread B takes
10and holds the 'client' lock while attempting to take the 'vm' lock.
11
12The potential for this can be seen as follows:
13
14Thread A:
15virLXCProcessAutostartDomain (takes vm lock)
16 --> virLXCProcessStart
17 --> virLXCProcessConnectMonitor
18 --> virLXCMonitorNew
19 --> virNetClientSetCloseCallback (wants client lock)
20
21Thread B:
22virNetClientIncomingEvent (takes client lock)
23 --> virNetClientIOHandleInput
24 --> virNetClientCallDispatch
25 --> virNetClientCallDispatchMessage
26 --> virNetClientProgramDispatch
27 --> virLXCMonitorHandleEventInit
28 --> virLXCProcessMonitorInitNotify (wants vm lock)
29
30Since these threads are scheduled independently and are preemptible it
31is possible for the deadlock scenario to occur where each thread locks
32their first lock but both will fail to get their second lock and just
33spin forever. You get something like:
34
35virLXCProcessAutostartDomain (takes vm lock)
36 --> virLXCProcessStart
37 --> virLXCProcessConnectMonitor
38 --> virLXCMonitorNew
39<...>
40virNetClientIncomingEvent (takes client lock)
41 --> virNetClientIOHandleInput
42 --> virNetClientCallDispatch
43 --> virNetClientCallDispatchMessage
44 --> virNetClientProgramDispatch
45 --> virLXCMonitorHandleEventInit
46 --> virLXCProcessMonitorInitNotify (wants vm lock but spins)
47<...>
48 --> virNetClientSetCloseCallback (wants client lock but spins)
49
50Neither thread ever gets the lock it needs to be able to continue
51while holding the lock that the other thread needs.
52
53The actual window for preemption which can cause this deadlock is
54rather small, between the calls to virNetClientProgramNew() and
55execution of virNetClientSetCloseCallback(), both in
56virLXCMonitorNew(). But it can be seen in real world use that this
57small window is enough.
58
59By moving the call to virNetClientSetCloseCallback() ahead of
60virNetClientProgramNew() we can close any possible chance of the
61deadlock taking place. There should be no other implications to the
62move since the close callback (in the unlikely event was called) will
63spin on the vm lock. The remaining work that takes place between the
64old call location of virNetClientSetCloseCallback() and the new
65location is unaffected by the move.
66
67Upstream-Status: Backport commit 7882c6eca53f
68
69Signed-off-by: Mark Asselstine <mark.asselstine@windriver.com>
70Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
71---
72 src/lxc/lxc_monitor.c | 11 +++++++----
73 1 file changed, 7 insertions(+), 4 deletions(-)
74
75diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c
76index e765c16..0b18a14 100644
77--- a/src/lxc/lxc_monitor.c
78+++ b/src/lxc/lxc_monitor.c
79@@ -161,6 +161,13 @@ virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm,
80 if (virNetClientRegisterAsyncIO(mon->client) < 0)
81 goto error;
82
83+ /* avoid deadlock by making this call before assigning virLXCMonitorEvents */
84+ virNetClientSetCloseCallback(mon->client, virLXCMonitorEOFNotify, mon,
85+ virLXCMonitorCloseFreeCallback);
86+
87+ /* close callback now has its own reference */
88+ virObjectRef(mon);
89+
90 if (!(mon->program = virNetClientProgramNew(VIR_LXC_MONITOR_PROGRAM,
91 VIR_LXC_MONITOR_PROGRAM_VERSION,
92 virLXCMonitorEvents,
93@@ -175,10 +182,6 @@ virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm,
94 mon->vm = virObjectRef(vm);
95 memcpy(&mon->cb, cb, sizeof(mon->cb));
96
97- virObjectRef(mon);
98- virNetClientSetCloseCallback(mon->client, virLXCMonitorEOFNotify, mon,
99- virLXCMonitorCloseFreeCallback);
100-
101 cleanup:
102 VIR_FREE(sockpath);
103 return mon;
104--
1052.7.4
106
diff --git a/recipes-extended/libvirt/libvirt_4.7.0.bb b/recipes-extended/libvirt/libvirt_4.7.0.bb
index 14565dae..47275ae6 100644
--- a/recipes-extended/libvirt/libvirt_4.7.0.bb
+++ b/recipes-extended/libvirt/libvirt_4.7.0.bb
@@ -35,6 +35,7 @@ SRC_URI = "http://libvirt.org/sources/libvirt-${PV}.tar.xz;name=libvirt \
35 file://install-missing-file.patch \ 35 file://install-missing-file.patch \
36 file://0001-ptest-Remove-Windows-1252-check-from-esxutilstest.patch \ 36 file://0001-ptest-Remove-Windows-1252-check-from-esxutilstest.patch \
37 file://configure.ac-search-for-rpc-rpc.h-in-the-sysroot.patch \ 37 file://configure.ac-search-for-rpc-rpc.h-in-the-sysroot.patch \
38 file://lxc_monitor-Avoid-AB-BA-lock-race.patch \
38 " 39 "
39 40
40SRC_URI[libvirt.md5sum] = "38da6c33250dcbc0a6d68de5c758262b" 41SRC_URI[libvirt.md5sum] = "38da6c33250dcbc0a6d68de5c758262b"