[PATCH v1] ioeventfd: introduce get_ioeventfd()

From: Zhenyu Ye
Date: Fri Jul 31 2020 - 04:59:55 EST


Get corresponding ioeventfd from kvm->ioeventfds. If no match
is found, return NULL. This is used in kvm_assign_ioeventfd_idx()
and kvm_deassign_ioeventfd_idx().

Signed-off-by: Zhenyu Ye <yezhenyu2@xxxxxxxxxx>
---
virt/kvm/eventfd.c | 53 ++++++++++++++++++++++++----------------------
1 file changed, 28 insertions(+), 25 deletions(-)

diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index ef7ed916ad4a..77f7d81c1138 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -28,6 +28,11 @@

#include <kvm/iodev.h>

+#define warn_if(expr, msg) do { \
+ if (expr) \
+ pr_warn("ioeventfd: %s\n", msg); \
+} while (0)
+
#ifdef CONFIG_HAVE_KVM_IRQFD

static struct workqueue_struct *irqfd_cleanup_wq;
@@ -756,21 +761,23 @@ static const struct kvm_io_device_ops ioeventfd_ops = {
};

/* assumes kvm->slots_lock held */
-static bool
-ioeventfd_check_collision(struct kvm *kvm, struct _ioeventfd *p)
+static inline struct _ioeventfd *
+get_ioeventfd(struct kvm *kvm, enum kvm_bus bus_idx,
+ struct kvm_ioeventfd *args)
{
- struct _ioeventfd *_p;
+ static struct _ioeventfd *_p;
+ bool wildcard = !(args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH);

list_for_each_entry(_p, &kvm->ioeventfds, list)
- if (_p->bus_idx == p->bus_idx &&
- _p->addr == p->addr &&
- (!_p->length || !p->length ||
- (_p->length == p->length &&
- (_p->wildcard || p->wildcard ||
- _p->datamatch == p->datamatch))))
- return true;
+ if (_p->bus_idx == bus_idx &&
+ _p->addr == args->addr &&
+ (!_p->length || !args->len ||
+ (_p->length == args->len &&
+ (_p->wildcard || wildcard ||
+ _p->datamatch == args->datamatch))))
+ return _p;

- return false;
+ return NULL;
}

static enum kvm_bus ioeventfd_bus_from_flags(__u32 flags)
@@ -816,7 +823,7 @@ static int kvm_assign_ioeventfd_idx(struct kvm *kvm,
mutex_lock(&kvm->slots_lock);

/* Verify that there isn't a match already */
- if (ioeventfd_check_collision(kvm, p)) {
+ if (get_ioeventfd(kvm, bus_idx, args)) {
ret = -EEXIST;
goto unlock_fail;
}
@@ -849,7 +856,7 @@ static int
kvm_deassign_ioeventfd_idx(struct kvm *kvm, enum kvm_bus bus_idx,
struct kvm_ioeventfd *args)
{
- struct _ioeventfd *p, *tmp;
+ struct _ioeventfd *p;
struct eventfd_ctx *eventfd;
struct kvm_io_bus *bus;
int ret = -ENOENT;
@@ -860,18 +867,15 @@ kvm_deassign_ioeventfd_idx(struct kvm *kvm, enum kvm_bus bus_idx,

mutex_lock(&kvm->slots_lock);

- list_for_each_entry_safe(p, tmp, &kvm->ioeventfds, list) {
+ p = get_ioeventfd(kvm, bus_idx, args);
+ if (p) {
bool wildcard = !(args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH);
-
- if (p->bus_idx != bus_idx ||
- p->eventfd != eventfd ||
- p->addr != args->addr ||
- p->length != args->len ||
- p->wildcard != wildcard)
- continue;
-
- if (!p->wildcard && p->datamatch != args->datamatch)
- continue;
+ warn_if(p->eventfd != eventfd, "eventfd should be the same!");
+ warn_if(p->length != args->len, "length should be the same!");
+ warn_if(p->length && p->wildcard != wildcard,
+ "wildcard should be the same!");
+ warn_if(p->length && !p->wildcard && p->datamatch != args->datamatch,
+ "datamatch should be the same!");

kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev);
bus = kvm_get_bus(kvm, bus_idx);
@@ -879,7 +883,6 @@ kvm_deassign_ioeventfd_idx(struct kvm *kvm, enum kvm_bus bus_idx,
bus->ioeventfd_count--;
ioeventfd_release(p);
ret = 0;
- break;
}

mutex_unlock(&kvm->slots_lock);
--
2.19.1