File 5c5df531-libxl-search-domid-in-thread.patch of Package libvirt
168
1
commit 5c5df5310f72be4878a71ace47074c54e0d1a27d
2
Author: Jim Fehlig <jfehlig@suse.com>
3
Date: Wed Nov 24 11:48:51 2021 -0700
4
5
libxl: Search for virDomainObj in event handler threads
6
7
libxl can deliver events and invoke callbacks on any application thread
8
calling into libxl. This can cause deadlock in the libvirt libxl driver
9
10
Thread 19 (Thread 0x7f31411ec700 (LWP 14068) "libvirtd"):
11
#0 0x00007f318520cc7d in __lll_lock_wait () from /lib64/libpthread.so.0
12
#1 0x00007f3185205ed5 in pthread_mutex_lock () from /lib64/libpthread.so.0
13
#2 0x00007f3189488015 in virMutexLock (m=<optimized out>) at ../../src/util/virthread.c:79
14
#3 0x00007f3189463f3b in virObjectLock (anyobj=<optimized out>) at ../../src/util/virobject.c:433
15
#4 0x00007f31894f2f41 in virDomainObjListSearchID (payload=0x7f317400a6d0, name=<optimized out>, data=0x7f31411eaeac) at ../../src/conf/virdomainobjlist.c:105
16
#5 0x00007f3189437ac5 in virHashSearch (ctable=0x7f3124025a30, iter=iter@entry=0x7f31894f2f30 <virDomainObjListSearchID>, data=data@entry=0x7f31411eaeac, name=name@entry=0x0) at ../../src/util/virhash.c:745
17
#6 0x00007f31894f3919 in virDomainObjListFindByID (doms=0x7f3124025430, id=<optimized out>) at ../../src/conf/virdomainobjlist.c:121
18
#7 0x00007f3152f292e5 in libxlDomainEventHandler (data=0x7f3124023d80, event=0x7f310c010ae0) at ../../src/libxl/libxl_domain.c:660
19
#8 0x00007f3152c6ff5d in egc_run_callbacks (egc=egc@entry=0x7f31411eaf50) at libxl_event.c:1427
20
#9 0x00007f3152c718bd in libxl__egc_cleanup (egc=0x7f31411eaf50) at libxl_event.c:1458
21
#10 libxl__ao_inprogress (ao=ao@entry=0x7f310c00b8a0, file=file@entry=0x7f3152cce987 "libxl_domain.c", line=line@entry=730, func=func@entry=0x7f3152ccf750 <__func__.22238> "libxl_domain_unpause") at libxl_event.c:2047
22
#11 0x00007f3152c8c5b8 in libxl_domain_unpause (ctx=0x7f3124015a40, domid=<optimized out>, ao_how=ao_how@entry=0x0) at libxl_domain.c:730
23
#12 0x00007f3152f2a584 in libxl_domain_unpause_0x041200 (domid=<optimized out>, ctx=<optimized out>) at /usr/include/libxl.h:1756
24
#13 libxlDomainStart (driver=driver@entry=0x7f3124023d80, vm=vm@entry=0x7f317400a6d0, start_paused=start_paused@entry=false, restore_fd=restore_fd@entry=-1, restore_ver=<optimized out>, restore_ver@entry=2) at ../../src/libxl/libxl_domain.c:1482
25
#14 0x00007f3152f2a6e3 in libxlDomainStartNew (driver=driver@entry=0x7f3124023d80, vm=vm@entry=0x7f317400a6d0, start_paused=start_paused@entry=false) at ../../src/libxl/libxl_domain.c:1545
26
#15 0x00007f3152f2a789 in libxlDomainShutdownHandleRestart (driver=0x7f3124023d80, vm=0x7f317400a6d0) at ../../src/libxl/libxl_domain.c:464
27
#16 0x00007f3152f2a9e4 in libxlDomainShutdownThread (opaque=<optimized out>) at ../../src/libxl/libxl_domain.c:559
28
#17 0x00007f3189487ee2 in virThreadHelper (data=<optimized out>) at ../../src/util/virthread.c:196
29
#18 0x00007f3185203539 in start_thread () from /lib64/libpthread.so.0
30
#19 0x00007f3184f3becf in clone () from /lib64/libc.so.6
31
32
Frame 16 runs a thread created to handle domain shutdown processing for
33
domid 28712. In this case the event contained the reboot reason, so the
34
old domain is destroyed and a new one is created by libxlDomainStart new.
35
After starting the domain, it is unpaused by calling libxl_domain_unpause
36
in frame 12. While the thread is running within libxl, libxl takes the
37
opportunity to deliver a pending domain shutdown event for unrelated domid
38
28710. While searching for the associated virDomainObj by ID, a deadlock is
39
encountered when attempting to lock the virDomainObj for domid 28712, which
40
is already locked since this thread is processing its shutdown event.
41
42
The deadlock can be avoided by moving the search for a virDomainObj
43
associated with the event domid to the shutdown thread. The same is done
44
for the death thread.
45
46
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
47
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
48
Reviewed-by: Ján Tomko <jtomko@redhat.com>
49
50
Index: libvirt-7.1.0/src/libxl/libxl_domain.c
51
===================================================================
52
--- libvirt-7.1.0.orig/src/libxl/libxl_domain.c
53
+++ libvirt-7.1.0/src/libxl/libxl_domain.c
54
55
struct libxlEventHandlerThreadInfo
56
{
57
libxlDriverPrivatePtr driver;
58
- virDomainObjPtr vm;
59
libxl_event *event;
60
};
61
62
63
libxlDomainShutdownThread(void *opaque)
64
{
65
struct libxlEventHandlerThreadInfo *shutdown_info = opaque;
66
- virDomainObjPtr vm = shutdown_info->vm;
67
+ virDomainObjPtr vm = NULL;
68
libxl_event *ev = shutdown_info->event;
69
libxlDriverPrivatePtr driver = shutdown_info->driver;
70
virObjectEventPtr dom_event = NULL;
71
72
73
libxl_domain_config_init(&d_config);
74
75
+ vm = virDomainObjListFindByID(driver->domains, ev->domid);
76
+ if (!vm) {
77
+ /* Nothing to do if we can't find the virDomainObj */
78
+ goto cleanup;
79
+ }
80
+
81
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
82
goto cleanup;
83
84
85
libxlDomainDeathThread(void *opaque)
86
{
87
struct libxlEventHandlerThreadInfo *death_info = opaque;
88
- virDomainObjPtr vm = death_info->vm;
89
+ virDomainObjPtr vm = NULL;
90
libxl_event *ev = death_info->event;
91
libxlDriverPrivatePtr driver = death_info->driver;
92
virObjectEventPtr dom_event = NULL;
93
g_autoptr(libxlDriverConfig) cfg = libxlDriverConfigGet(driver);
94
95
+ vm = virDomainObjListFindByID(driver->domains, ev->domid);
96
+ if (!vm) {
97
+ /* Nothing to do if we can't find the virDomainObj */
98
+ goto cleanup;
99
+ }
100
+
101
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
102
goto cleanup;
103
104
105
{
106
libxlDriverPrivatePtr driver = data;
107
libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason;
108
- virDomainObjPtr vm = NULL;
109
g_autoptr(libxlDriverConfig) cfg = NULL;
110
struct libxlEventHandlerThreadInfo *thread_info = NULL;
111
virThread thread;
112
113
if (xl_reason == LIBXL_SHUTDOWN_REASON_SUSPEND)
114
goto cleanup;
115
116
- vm = virDomainObjListFindByID(driver->domains, event->domid);
117
- if (!vm) {
118
- /* Nothing to do if we can't find the virDomainObj */
119
- goto cleanup;
120
- }
121
-
122
/*
123
* Start event-specific threads to handle shutdown and death.
124
* They are potentially lengthy operations and we don't want to be
125
126
thread_info = g_new0(struct libxlEventHandlerThreadInfo, 1);
127
128
thread_info->driver = driver;
129
- thread_info->vm = vm;
130
thread_info->event = (libxl_event *)event;
131
thread_name = g_strdup_printf("shutdown-event-%d", event->domid);
132
/*
133
134
goto cleanup;
135
}
136
/*
137
- * virDomainObjEndAPI is called in the shutdown thread, where
138
- * libxlEventHandlerThreadInfo and libxl_event are also freed.
139
+ * libxlEventHandlerThreadInfo and libxl_event are freed in the
140
+ * shutdown thread
141
*/
142
return;
143
} else if (event->type == LIBXL_EVENT_TYPE_DOMAIN_DEATH) {
144
thread_info = g_new0(struct libxlEventHandlerThreadInfo, 1);
145
146
thread_info->driver = driver;
147
- thread_info->vm = vm;
148
thread_info->event = (libxl_event *)event;
149
thread_name = g_strdup_printf("death-event-%d", event->domid);
150
/*
151
152
goto cleanup;
153
}
154
/*
155
- * virDomainObjEndAPI is called in the death thread, where
156
- * libxlEventHandlerThreadInfo and libxl_event are also freed.
157
+ * libxlEventHandlerThreadInfo and libxl_event are freed in the
158
+ * death thread
159
*/
160
return;
161
}
162
163
cleanup:
164
- virDomainObjEndAPI(&vm);
165
VIR_FREE(thread_info);
166
cfg = libxlDriverConfigGet(driver);
167
/* Cast away any const */
168