int ret = 0;
if (flags & EPOLLIN) {
+ /*
+ * WARNING: Do NOT take irqfds.lock in any path except EPOLLHUP,
+ * as KVM holds irqfds.lock when registering the irqfd with the
+ * eventfd.
+ */
u64 cnt;
eventfd_ctx_do_read(irqfd->eventfd, &cnt);
/* The eventfd is closing, detach from KVM */
unsigned long iflags;
+ /*
+ * Taking irqfds.lock is safe here, as KVM holds a reference to
+ * the eventfd when registering the irqfd, i.e. this path can't
+ * be reached while kvm_irqfd_add() is running.
+ */
spin_lock_irqsave(&kvm->irqfds.lock, iflags);
/*
list_add_tail(&irqfd->list, &kvm->irqfds.items);
- spin_unlock_irq(&kvm->irqfds.lock);
-
/*
* Add the irqfd as a priority waiter on the eventfd, with a custom
* wake-up handler, so that KVM *and only KVM* is notified whenever the
- * underlying eventfd is signaled.
+ * underlying eventfd is signaled. Temporarily lie to lockdep about
+ * holding irqfds.lock to avoid a false positive regarding potential
+ * deadlock with irqfd_wakeup() (see irqfd_wakeup() for details).
*/
init_waitqueue_func_entry(&irqfd->wait, irqfd_wakeup);
+ spin_release(&kvm->irqfds.lock.dep_map, _RET_IP_);
add_wait_queue_priority(wqh, &irqfd->wait);
+ spin_acquire(&kvm->irqfds.lock.dep_map, 0, 0, _RET_IP_);
+
+ spin_unlock_irq(&kvm->irqfds.lock);
+
p->ret = 0;
}