Skip to content

Commit baf8f8b

Browse files
chejianjwenlingz
authored andcommitted
dm: virtio-input: apply new mevent API to avoid race issue
Teardown callback is provided when mevent_add is called and it is used to free the virtio-input resources. Tracked-On: #1877 Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com> Acked-by: Yin Fengwei <fengwei.yin@intel.com>
1 parent c2df4a8 commit baf8f8b

File tree

1 file changed

+55
-51
lines changed

1 file changed

+55
-51
lines changed

devicemodel/hw/pci/virtio/virtio_input.c

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -543,12 +543,32 @@ virtio_input_get_config(struct virtio_input *vi, uint8_t select,
543543
return found;
544544
}
545545

546+
static void
547+
virtio_input_teardown(void *param)
548+
{
549+
struct virtio_input *vi;
550+
551+
vi = (struct virtio_input *)param;
552+
if (vi) {
553+
pthread_mutex_destroy(&vi->mtx);
554+
if (vi->event_queue)
555+
free(vi->event_queue);
556+
if (vi->fd > 0)
557+
close(vi->fd);
558+
if (vi->evdev)
559+
free(vi->evdev);
560+
if (vi->serial)
561+
free(vi->serial);
562+
free(vi);
563+
vi = NULL;
564+
}
565+
}
566+
546567
static int
547568
virtio_input_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
548569
{
549570
struct virtio_input *vi;
550571
pthread_mutexattr_t attr;
551-
bool mutex_initialized = false;
552572
char *opt;
553573
int flags, ver;
554574
int rc;
@@ -570,41 +590,41 @@ virtio_input_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
570590
opt = strsep(&opts, ",");
571591
if (!opt) {
572592
WPRINTF(("%s: evdev path is NULL\n", __func__));
573-
goto fail;
593+
goto opt_fail;
574594
}
575595

576596
vi->evdev = strdup(opt);
577597
if (!vi->evdev) {
578598
WPRINTF(("%s: strdup failed\n", __func__));
579-
goto fail;
599+
goto opt_fail;
580600
}
581601

582602
if (opts) {
583603
vi->serial = strdup(opts);
584604
if (!vi->serial) {
585605
WPRINTF(("%s: strdup serial failed\n", __func__));
586-
goto fail;
606+
goto serial_fail;
587607
}
588608
}
589609

590610
vi->fd = open(vi->evdev, O_RDWR);
591611
if (vi->fd < 0) {
592612
WPRINTF(("open %s failed %d\n", vi->evdev, errno));
593-
goto fail;
613+
goto open_fail;
594614
}
595615
flags = fcntl(vi->fd, F_GETFL);
596616
fcntl(vi->fd, F_SETFL, flags | O_NONBLOCK);
597617

598618
rc = ioctl(vi->fd, EVIOCGVERSION, &ver); /* is it a evdev device? */
599619
if (rc < 0) {
600620
WPRINTF(("%s: get version failed\n", vi->evdev));
601-
goto fail;
621+
goto evdev_fail;
602622
}
603623

604624
rc = ioctl(vi->fd, EVIOCGRAB, 1); /* exclusive access */
605625
if (rc < 0) {
606626
WPRINTF(("%s: grab device failed %d\n", vi->evdev, errno));
607-
goto fail;
627+
goto evdev_fail;
608628
}
609629

610630
/* init mutex attribute properly to avoid deadlock */
@@ -619,21 +639,21 @@ virtio_input_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
619639
if (rc)
620640
DPRINTF(("vtinput: pthread_mutex_init failed with "
621641
"error %d!\n", rc));
622-
mutex_initialized = (rc == 0) ? true : false;
623642

624643
vi->event_qsize = VIRTIO_INPUT_PACKET_SIZE;
625644
vi->event_qindex = 0;
626645
vi->event_queue = calloc(vi->event_qsize,
627646
sizeof(struct virtio_input_event_elem));
628647
if (!vi->event_queue) {
629648
WPRINTF(("vtinput: could not alloc event queue buf\n"));
630-
goto fail;
649+
goto evqueue_fail;
631650
}
632651

633-
vi->mevp = mevent_add(vi->fd, EVF_READ, virtio_input_read_event, vi, NULL, NULL);
652+
vi->mevp = mevent_add(vi->fd, EVF_READ, virtio_input_read_event, vi,
653+
virtio_input_teardown, vi);
634654
if (vi->mevp == NULL) {
635655
WPRINTF(("vtinput: could not register event\n"));
636-
goto fail;
656+
goto mevent_fail;
637657
}
638658

639659
virtio_linkup(&vi->base, &virtio_input_ops, vi, dev, vi->queues, BACKEND_VBSU);
@@ -665,32 +685,29 @@ virtio_input_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
665685
return rc;
666686

667687
fail:
668-
if (vi) {
669-
if (mutex_initialized)
670-
pthread_mutex_destroy(&vi->mtx);
671-
if (vi->event_queue) {
672-
free(vi->event_queue);
673-
vi->event_queue = NULL;
674-
}
675-
if (vi->mevp) {
676-
mevent_delete(vi->mevp);
677-
vi->mevp = NULL;
678-
}
679-
if (vi->fd > 0) {
680-
close(vi->fd);
681-
vi->fd = -1;
682-
}
683-
if (vi->serial) {
684-
free(vi->serial);
685-
vi->serial = NULL;
686-
}
687-
if (vi->evdev) {
688-
free(vi->evdev);
689-
vi->evdev = NULL;
690-
}
691-
free(vi);
692-
vi = NULL;
688+
/* all resources will be freed in the teardown callback */
689+
mevent_delete(vi->mevp);
690+
return -1;
691+
692+
mevent_fail:
693+
free(vi->event_queue);
694+
vi->event_queue = NULL;
695+
evqueue_fail:
696+
pthread_mutex_destroy(&vi->mtx);
697+
evdev_fail:
698+
close(vi->fd);
699+
vi->fd = -1;
700+
open_fail:
701+
if (vi->serial) {
702+
free(vi->serial);
703+
vi->serial = NULL;
693704
}
705+
serial_fail:
706+
free(vi->evdev);
707+
vi->evdev = NULL;
708+
opt_fail:
709+
free(vi);
710+
vi = NULL;
694711
return -1;
695712
}
696713

@@ -700,21 +717,8 @@ virtio_input_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
700717
struct virtio_input *vi;
701718

702719
vi = (struct virtio_input *)dev->arg;
703-
if (vi) {
704-
pthread_mutex_destroy(&vi->mtx);
705-
if (vi->event_queue)
706-
free(vi->event_queue);
707-
if (vi->mevp)
708-
mevent_delete(vi->mevp);
709-
if (vi->fd > 0)
710-
close(vi->fd);
711-
if (vi->evdev)
712-
free(vi->evdev);
713-
if (vi->serial)
714-
free(vi->serial);
715-
free(vi);
716-
vi = NULL;
717-
}
720+
if (vi && vi->mevp)
721+
mevent_delete(vi->mevp);
718722
}
719723

720724
struct pci_vdev_ops pci_ops_virtio_input = {

0 commit comments

Comments
 (0)