@@ -192,17 +192,27 @@ static void vhost_user_blk_set_status(VirtIODevice *vdev, uint8_t status)
192
192
{
193
193
VHostUserBlk * s = VHOST_USER_BLK (vdev );
194
194
bool should_start = vdev -> started ;
195
+ int ret ;
195
196
196
197
if (!vdev -> vm_running ) {
197
198
should_start = false;
198
199
}
199
200
201
+ if (!s -> connected ) {
202
+ return ;
203
+ }
204
+
200
205
if (s -> dev .started == should_start ) {
201
206
return ;
202
207
}
203
208
204
209
if (should_start ) {
205
- vhost_user_blk_start (vdev );
210
+ ret = vhost_user_blk_start (vdev );
211
+ if (ret < 0 ) {
212
+ error_report ("vhost-user-blk: vhost start failed: %s" ,
213
+ strerror (- ret ));
214
+ qemu_chr_fe_disconnect (& s -> chardev );
215
+ }
206
216
} else {
207
217
vhost_user_blk_stop (vdev );
208
218
}
@@ -238,20 +248,30 @@ static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev,
238
248
static void vhost_user_blk_handle_output (VirtIODevice * vdev , VirtQueue * vq )
239
249
{
240
250
VHostUserBlk * s = VHOST_USER_BLK (vdev );
241
- int i ;
251
+ int i , ret ;
242
252
243
253
if (!vdev -> start_on_kick ) {
244
254
return ;
245
255
}
246
256
257
+ if (!s -> connected ) {
258
+ return ;
259
+ }
260
+
247
261
if (s -> dev .started ) {
248
262
return ;
249
263
}
250
264
251
265
/* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start
252
266
* vhost here instead of waiting for .set_status().
253
267
*/
254
- vhost_user_blk_start (vdev );
268
+ ret = vhost_user_blk_start (vdev );
269
+ if (ret < 0 ) {
270
+ error_report ("vhost-user-blk: vhost start failed: %s" ,
271
+ strerror (- ret ));
272
+ qemu_chr_fe_disconnect (& s -> chardev );
273
+ return ;
274
+ }
255
275
256
276
/* Kick right away to begin processing requests already in vring */
257
277
for (i = 0 ; i < s -> dev .nvqs ; i ++ ) {
@@ -271,11 +291,103 @@ static void vhost_user_blk_reset(VirtIODevice *vdev)
271
291
vhost_dev_free_inflight (s -> inflight );
272
292
}
273
293
294
+ static int vhost_user_blk_connect (DeviceState * dev )
295
+ {
296
+ VirtIODevice * vdev = VIRTIO_DEVICE (dev );
297
+ VHostUserBlk * s = VHOST_USER_BLK (vdev );
298
+ int ret = 0 ;
299
+
300
+ if (s -> connected ) {
301
+ return 0 ;
302
+ }
303
+ s -> connected = true;
304
+
305
+ s -> dev .nvqs = s -> num_queues ;
306
+ s -> dev .vqs = s -> vqs ;
307
+ s -> dev .vq_index = 0 ;
308
+ s -> dev .backend_features = 0 ;
309
+
310
+ vhost_dev_set_config_notifier (& s -> dev , & blk_ops );
311
+
312
+ ret = vhost_dev_init (& s -> dev , & s -> vhost_user , VHOST_BACKEND_TYPE_USER , 0 );
313
+ if (ret < 0 ) {
314
+ error_report ("vhost-user-blk: vhost initialization failed: %s" ,
315
+ strerror (- ret ));
316
+ return ret ;
317
+ }
318
+
319
+ /* restore vhost state */
320
+ if (vdev -> started ) {
321
+ ret = vhost_user_blk_start (vdev );
322
+ if (ret < 0 ) {
323
+ error_report ("vhost-user-blk: vhost start failed: %s" ,
324
+ strerror (- ret ));
325
+ return ret ;
326
+ }
327
+ }
328
+
329
+ return 0 ;
330
+ }
331
+
332
+ static void vhost_user_blk_disconnect (DeviceState * dev )
333
+ {
334
+ VirtIODevice * vdev = VIRTIO_DEVICE (dev );
335
+ VHostUserBlk * s = VHOST_USER_BLK (vdev );
336
+
337
+ if (!s -> connected ) {
338
+ return ;
339
+ }
340
+ s -> connected = false;
341
+
342
+ if (s -> dev .started ) {
343
+ vhost_user_blk_stop (vdev );
344
+ }
345
+
346
+ vhost_dev_cleanup (& s -> dev );
347
+ }
348
+
349
+ static gboolean vhost_user_blk_watch (GIOChannel * chan , GIOCondition cond ,
350
+ void * opaque )
351
+ {
352
+ DeviceState * dev = opaque ;
353
+ VirtIODevice * vdev = VIRTIO_DEVICE (dev );
354
+ VHostUserBlk * s = VHOST_USER_BLK (vdev );
355
+
356
+ qemu_chr_fe_disconnect (& s -> chardev );
357
+
358
+ return true;
359
+ }
360
+
361
+ static void vhost_user_blk_event (void * opaque , int event )
362
+ {
363
+ DeviceState * dev = opaque ;
364
+ VirtIODevice * vdev = VIRTIO_DEVICE (dev );
365
+ VHostUserBlk * s = VHOST_USER_BLK (vdev );
366
+
367
+ switch (event ) {
368
+ case CHR_EVENT_OPENED :
369
+ if (vhost_user_blk_connect (dev ) < 0 ) {
370
+ qemu_chr_fe_disconnect (& s -> chardev );
371
+ return ;
372
+ }
373
+ s -> watch = qemu_chr_fe_add_watch (& s -> chardev , G_IO_HUP ,
374
+ vhost_user_blk_watch , dev );
375
+ break ;
376
+ case CHR_EVENT_CLOSED :
377
+ vhost_user_blk_disconnect (dev );
378
+ if (s -> watch ) {
379
+ g_source_remove (s -> watch );
380
+ s -> watch = 0 ;
381
+ }
382
+ break ;
383
+ }
384
+ }
385
+
274
386
static void vhost_user_blk_device_realize (DeviceState * dev , Error * * errp )
275
387
{
276
388
VirtIODevice * vdev = VIRTIO_DEVICE (dev );
277
389
VHostUserBlk * s = VHOST_USER_BLK (vdev );
278
- struct vhost_virtqueue * vqs = NULL ;
390
+ Error * err = NULL ;
279
391
int i , ret ;
280
392
281
393
if (!s -> chardev .chr ) {
@@ -306,27 +418,29 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
306
418
}
307
419
308
420
s -> inflight = g_new0 (struct vhost_inflight , 1 );
421
+ s -> vqs = g_new (struct vhost_virtqueue , s -> num_queues );
422
+ s -> watch = 0 ;
423
+ s -> connected = false;
309
424
310
- s -> dev .nvqs = s -> num_queues ;
311
- s -> dev .vqs = g_new (struct vhost_virtqueue , s -> dev .nvqs );
312
- s -> dev .vq_index = 0 ;
313
- s -> dev .backend_features = 0 ;
314
- vqs = s -> dev .vqs ;
315
-
316
- vhost_dev_set_config_notifier (& s -> dev , & blk_ops );
425
+ qemu_chr_fe_set_handlers (& s -> chardev , NULL , NULL , vhost_user_blk_event ,
426
+ NULL , (void * )dev , NULL , true);
317
427
318
- ret = vhost_dev_init (& s -> dev , & s -> vhost_user , VHOST_BACKEND_TYPE_USER , 0 );
319
- if (ret < 0 ) {
320
- error_setg (errp , "vhost-user-blk: vhost initialization failed: %s" ,
321
- strerror (- ret ));
428
+ reconnect :
429
+ if (qemu_chr_fe_wait_connected (& s -> chardev , & err ) < 0 ) {
430
+ error_report_err (err );
322
431
goto virtio_err ;
323
432
}
324
433
434
+ /* check whether vhost_user_blk_connect() failed or not */
435
+ if (!s -> connected ) {
436
+ goto reconnect ;
437
+ }
438
+
325
439
ret = vhost_dev_get_config (& s -> dev , (uint8_t * )& s -> blkcfg ,
326
- sizeof (struct virtio_blk_config ));
440
+ sizeof (struct virtio_blk_config ));
327
441
if (ret < 0 ) {
328
- error_setg ( errp , "vhost-user-blk: get block config failed" );
329
- goto vhost_err ;
442
+ error_report ( "vhost-user-blk: get block config failed" );
443
+ goto reconnect ;
330
444
}
331
445
332
446
if (s -> blkcfg .num_queues != s -> num_queues ) {
@@ -335,10 +449,8 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
335
449
336
450
return ;
337
451
338
- vhost_err :
339
- vhost_dev_cleanup (& s -> dev );
340
452
virtio_err :
341
- g_free (vqs );
453
+ g_free (s -> vqs );
342
454
g_free (s -> inflight );
343
455
virtio_cleanup (vdev );
344
456
vhost_user_cleanup (& s -> vhost_user );
@@ -348,12 +460,13 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp)
348
460
{
349
461
VirtIODevice * vdev = VIRTIO_DEVICE (dev );
350
462
VHostUserBlk * s = VHOST_USER_BLK (dev );
351
- struct vhost_virtqueue * vqs = s -> dev .vqs ;
352
463
353
464
virtio_set_status (vdev , 0 );
465
+ qemu_chr_fe_set_handlers (& s -> chardev , NULL , NULL , NULL ,
466
+ NULL , NULL , NULL , false);
354
467
vhost_dev_cleanup (& s -> dev );
355
468
vhost_dev_free_inflight (s -> inflight );
356
- g_free (vqs );
469
+ g_free (s -> vqs );
357
470
g_free (s -> inflight );
358
471
virtio_cleanup (vdev );
359
472
vhost_user_cleanup (& s -> vhost_user );
0 commit comments