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