qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

vhost-user: delay vhost_user_stop

Since commit b0a335e351103bf92f3f9d0bd5759311be8156ac, a socket write
may trigger a disconnect events, calling vhost_user_stop() and clearing
all the vhost_dev strutures holding data that vhost.c functions expect
to remain valid. Delay the cleanup to keep the vhost_dev structure
valid during the vhost.c functions.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-id: 20170227104956.24729-1-marcandre.lureau@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

authored by

Marc-André Lureau and committed by
Peter Maydell
e7c83a88 9514f264

+46 -7
+46 -7
net/vhost-user.c
··· 190 190 191 191 qemu_chr_fe_disconnect(&s->chr); 192 192 193 - return FALSE; 193 + return TRUE; 194 + } 195 + 196 + static void net_vhost_user_event(void *opaque, int event); 197 + 198 + static void chr_closed_bh(void *opaque) 199 + { 200 + const char *name = opaque; 201 + NetClientState *ncs[MAX_QUEUE_NUM]; 202 + VhostUserState *s; 203 + Error *err = NULL; 204 + int queues; 205 + 206 + queues = qemu_find_net_clients_except(name, ncs, 207 + NET_CLIENT_DRIVER_NIC, 208 + MAX_QUEUE_NUM); 209 + assert(queues < MAX_QUEUE_NUM); 210 + 211 + s = DO_UPCAST(VhostUserState, nc, ncs[0]); 212 + 213 + qmp_set_link(name, false, &err); 214 + vhost_user_stop(queues, ncs); 215 + 216 + qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event, 217 + opaque, NULL, true); 218 + 219 + if (err) { 220 + error_report_err(err); 221 + } 194 222 } 195 223 196 224 static void net_vhost_user_event(void *opaque, int event) ··· 212 240 trace_vhost_user_event(chr->label, event); 213 241 switch (event) { 214 242 case CHR_EVENT_OPENED: 215 - s->watch = qemu_chr_fe_add_watch(&s->chr, G_IO_HUP, 216 - net_vhost_user_watch, s); 217 243 if (vhost_user_start(queues, ncs, &s->chr) < 0) { 218 244 qemu_chr_fe_disconnect(&s->chr); 219 245 return; 220 246 } 247 + s->watch = qemu_chr_fe_add_watch(&s->chr, G_IO_HUP, 248 + net_vhost_user_watch, s); 221 249 qmp_set_link(name, true, &err); 222 250 s->started = true; 223 251 break; 224 252 case CHR_EVENT_CLOSED: 225 - qmp_set_link(name, false, &err); 226 - vhost_user_stop(queues, ncs); 227 - g_source_remove(s->watch); 228 - s->watch = 0; 253 + /* a close event may happen during a read/write, but vhost 254 + * code assumes the vhost_dev remains setup, so delay the 255 + * stop & clear to idle. 256 + * FIXME: better handle failure in vhost code, remove bh 257 + */ 258 + if (s->watch) { 259 + AioContext *ctx = qemu_get_current_aio_context(); 260 + 261 + g_source_remove(s->watch); 262 + s->watch = 0; 263 + qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, 264 + NULL, NULL, false); 265 + 266 + aio_bh_schedule_oneshot(ctx, chr_closed_bh, opaque); 267 + } 229 268 break; 230 269 } 231 270