[RFC 06/12] kvm tools: Fixes for ioeventfd module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Fixes include:
 - Error handling
 - Cleanup
 - Standard init/uninit

Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx>
---
 tools/kvm/builtin-run.c           |   12 ++-
 tools/kvm/include/kvm/ioeventfd.h |    8 +-
 tools/kvm/ioeventfd.c             |  158 ++++++++++++++++++++++++++-----------
 tools/kvm/virtio/pci.c            |    5 +-
 4 files changed, 128 insertions(+), 55 deletions(-)

diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
index 5388171..b7e7977 100644
--- a/tools/kvm/builtin-run.c
+++ b/tools/kvm/builtin-run.c
@@ -958,7 +958,11 @@ static int kvm_cmd_run_init(int argc, const char **argv)
 
 	kvm->single_step = single_step;
 
-	ioeventfd__init(kvm);
+	r = ioeventfd__init(kvm);
+	if (r < 0) {
+		pr_error("ioeventfd__init() failed with error %d\n", r);
+		goto fail;
+	}
 
 	max_cpus = kvm__max_cpus(kvm);
 	recommended_cpus = kvm__recommended_cpus(kvm);
@@ -1158,8 +1162,6 @@ static int kvm_cmd_run_init(int argc, const char **argv)
 	}
 
 	thread_pool__init(nr_online_cpus);
-	ioeventfd__start();
-
 fail:
 	return r;
 }
@@ -1216,6 +1218,10 @@ static void kvm_cmd_run_uninit(int guest_ret)
 	if (r < 0)
 		pr_warning("ioport__uninit() failed with error %d\n", r);
 
+	r = ioeventfd__uninit(kvm);
+	if (r < 0)
+		pr_warning("ioeventfd__uninit() failed with error %d\n", r);
+
 	kvm__delete(kvm);
 
 	if (guest_ret == 0)
diff --git a/tools/kvm/include/kvm/ioeventfd.h b/tools/kvm/include/kvm/ioeventfd.h
index 3a95788..cb8a21b 100644
--- a/tools/kvm/include/kvm/ioeventfd.h
+++ b/tools/kvm/include/kvm/ioeventfd.h
@@ -19,9 +19,9 @@ struct ioevent {
 	struct list_head	list;
 };
 
-void ioeventfd__init(struct kvm *kvm);
-void ioeventfd__start(void);
-void ioeventfd__add_event(struct ioevent *ioevent);
-void ioeventfd__del_event(u64 addr, u64 datamatch);
+int ioeventfd__init(struct kvm *kvm);
+int ioeventfd__uninit(struct kvm *kvm);
+int ioeventfd__add_event(struct ioevent *ioevent);
+int ioeventfd__del_event(u64 addr, u64 datamatch);
 
 #endif
diff --git a/tools/kvm/ioeventfd.c b/tools/kvm/ioeventfd.c
index 1d6a7ac..bb248d7 100644
--- a/tools/kvm/ioeventfd.c
+++ b/tools/kvm/ioeventfd.c
@@ -16,34 +16,117 @@
 #define IOEVENTFD_MAX_EVENTS	20
 
 static struct	epoll_event events[IOEVENTFD_MAX_EVENTS];
-static int	epoll_fd;
+static int	epoll_fd, epoll_stop_fd;
 static LIST_HEAD(used_ioevents);
 static bool	ioeventfd_avail;
 
-void ioeventfd__init(struct kvm *kvm)
+static void *ioeventfd__thread(void *param)
 {
+	u64 tmp = 1;
+
+	for (;;) {
+		int nfds, i;
+
+		nfds = epoll_wait(epoll_fd, events, IOEVENTFD_MAX_EVENTS, -1);
+		for (i = 0; i < nfds; i++) {
+			struct ioevent *ioevent;
+
+			if (events[i].data.fd == epoll_stop_fd)
+				goto done;
+
+			ioevent = events[i].data.ptr;
+
+			if (read(ioevent->fd, &tmp, sizeof(tmp)) < 0)
+				die("Failed reading event");
+
+			ioevent->fn(ioevent->fn_kvm, ioevent->fn_ptr);
+		}
+	}
+
+done:
+	tmp = 1;
+	tmp = write(epoll_stop_fd, &tmp, sizeof(tmp));
+
+	return NULL;
+}
+
+static int ioeventfd__start(void)
+{
+	pthread_t thread;
+
+	if (!ioeventfd_avail)
+		return -ENOSYS;
+
+	return pthread_create(&thread, NULL, ioeventfd__thread, NULL);
+}
+
+int ioeventfd__init(struct kvm *kvm)
+{
+	struct epoll_event epoll_event = {.events = EPOLLIN};
+	int r;
+
 	ioeventfd_avail = kvm__supports_extension(kvm, KVM_CAP_IOEVENTFD);
 	if (!ioeventfd_avail)
-		return;
+		return -ENOSYS;
 
 	epoll_fd = epoll_create(IOEVENTFD_MAX_EVENTS);
 	if (epoll_fd < 0)
-		die("Failed creating epoll fd");
+		return -errno;
+
+	epoll_stop_fd = eventfd(0, 0);
+	epoll_event.data.fd = epoll_stop_fd;
+
+	r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, epoll_stop_fd, &epoll_event);
+	if (r < 0)
+		goto cleanup;
+
+	r = ioeventfd__start();
+	if (r < 0)
+		goto cleanup;
+
+	r = 0;
+
+	return r;
+
+cleanup:
+	close(epoll_stop_fd);
+	close(epoll_fd);
+
+	return r;
 }
 
-void ioeventfd__add_event(struct ioevent *ioevent)
+int ioeventfd__uninit(struct kvm *kvm)
+{
+	u64 tmp = 1;
+	int r;
+
+	r = write(epoll_stop_fd, &tmp, sizeof(tmp));
+	if (r < 0)
+		return r;
+
+	r = read(epoll_stop_fd, &tmp, sizeof(tmp));
+	if (r < 0)
+		return r;
+
+	close(epoll_fd);
+	close(epoll_stop_fd);
+
+	return 0;
+}
+
+int ioeventfd__add_event(struct ioevent *ioevent)
 {
 	struct kvm_ioeventfd kvm_ioevent;
 	struct epoll_event epoll_event;
 	struct ioevent *new_ioevent;
-	int event;
+	int event, r;
 
 	if (!ioeventfd_avail)
-		return;
+		return -ENOSYS;
 
 	new_ioevent = malloc(sizeof(*new_ioevent));
 	if (new_ioevent == NULL)
-		die("Failed allocating memory for new ioevent");
+		return -ENOMEM;
 
 	*new_ioevent = *ioevent;
 	event = new_ioevent->fd;
@@ -56,28 +139,40 @@ void ioeventfd__add_event(struct ioevent *ioevent)
 		.flags			= KVM_IOEVENTFD_FLAG_PIO | KVM_IOEVENTFD_FLAG_DATAMATCH,
 	};
 
-	if (ioctl(ioevent->fn_kvm->vm_fd, KVM_IOEVENTFD, &kvm_ioevent) != 0)
-		die("Failed creating new ioeventfd");
+	r = ioctl(ioevent->fn_kvm->vm_fd, KVM_IOEVENTFD, &kvm_ioevent);
+	if (r) {
+		r = -errno;
+		goto cleanup;
+	}
 
 	epoll_event = (struct epoll_event) {
 		.events			= EPOLLIN,
 		.data.ptr		= new_ioevent,
 	};
 
-	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, event, &epoll_event) != 0)
-		die("Failed assigning new event to the epoll fd");
+	r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, event, &epoll_event);
+	if (r) {
+		r = -errno;
+		goto cleanup;
+	}
 
 	list_add_tail(&new_ioevent->list, &used_ioevents);
+
+	return 0;
+
+cleanup:
+	free(new_ioevent);
+	return r;
 }
 
-void ioeventfd__del_event(u64 addr, u64 datamatch)
+int ioeventfd__del_event(u64 addr, u64 datamatch)
 {
 	struct kvm_ioeventfd kvm_ioevent;
 	struct ioevent *ioevent;
 	u8 found = 0;
 
 	if (!ioeventfd_avail)
-		return;
+		return -ENOSYS;
 
 	list_for_each_entry(ioevent, &used_ioevents, list) {
 		if (ioevent->io_addr == addr) {
@@ -87,7 +182,7 @@ void ioeventfd__del_event(u64 addr, u64 datamatch)
 	}
 
 	if (found == 0 || ioevent == NULL)
-		return;
+		return -ENOENT;
 
 	kvm_ioevent = (struct kvm_ioeventfd) {
 		.addr			= ioevent->io_addr,
@@ -106,37 +201,6 @@ void ioeventfd__del_event(u64 addr, u64 datamatch)
 
 	close(ioevent->fd);
 	free(ioevent);
-}
-
-static void *ioeventfd__thread(void *param)
-{
-	for (;;) {
-		int nfds, i;
-
-		nfds = epoll_wait(epoll_fd, events, IOEVENTFD_MAX_EVENTS, -1);
-		for (i = 0; i < nfds; i++) {
-			u64 tmp;
-			struct ioevent *ioevent;
-
-			ioevent = events[i].data.ptr;
-
-			if (read(ioevent->fd, &tmp, sizeof(tmp)) < 0)
-				die("Failed reading event");
-
-			ioevent->fn(ioevent->fn_kvm, ioevent->fn_ptr);
-		}
-	}
-
-	return NULL;
-}
-
-void ioeventfd__start(void)
-{
-	pthread_t thread;
-
-	if (!ioeventfd_avail)
-		return;
 
-	if (pthread_create(&thread, NULL, ioeventfd__thread, NULL) != 0)
-		die("Failed starting ioeventfd thread");
+	return 0;
 }
diff --git a/tools/kvm/virtio/pci.c b/tools/kvm/virtio/pci.c
index 2643d8a..7cc014e 100644
--- a/tools/kvm/virtio/pci.c
+++ b/tools/kvm/virtio/pci.c
@@ -34,6 +34,7 @@ static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_trans *vtra
 {
 	struct ioevent ioevent;
 	struct virtio_pci *vpci = vtrans->virtio;
+	int r;
 
 	vpci->ioeventfds[vq] = (struct virtio_pci_ioevent_param) {
 		.vtrans		= vtrans,
@@ -50,7 +51,9 @@ static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_trans *vtra
 		.fd		= eventfd(0, 0),
 	};
 
-	ioeventfd__add_event(&ioevent);
+	r = ioeventfd__add_event(&ioevent);
+	if (r)
+		return r;
 
 	if (vtrans->virtio_ops->notify_vq_eventfd)
 		vtrans->virtio_ops->notify_vq_eventfd(kvm, vpci->dev, vq, ioevent.fd);
-- 
1.7.8

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux