void (*thread)(struct vfio_pci_device *, void *),
                         void *data, struct virqfd **pvirqfd, int fd)
 {
-       struct file *file = NULL;
-       struct eventfd_ctx *ctx = NULL;
+       struct fd irqfd;
+       struct eventfd_ctx *ctx;
        struct virqfd *virqfd;
        int ret = 0;
        unsigned int events;
        INIT_WORK(&virqfd->shutdown, virqfd_shutdown);
        INIT_WORK(&virqfd->inject, virqfd_inject);
 
-       file = eventfd_fget(fd);
-       if (IS_ERR(file)) {
-               ret = PTR_ERR(file);
-               goto fail;
+       irqfd = fdget(fd);
+       if (!irqfd.file) {
+               ret = -EBADF;
+               goto err_fd;
        }
 
-       ctx = eventfd_ctx_fileget(file);
+       ctx = eventfd_ctx_fileget(irqfd.file);
        if (IS_ERR(ctx)) {
                ret = PTR_ERR(ctx);
-               goto fail;
+               goto err_ctx;
        }
 
        virqfd->eventfd = ctx;
        if (*pvirqfd) {
                spin_unlock_irq(&vdev->irqlock);
                ret = -EBUSY;
-               goto fail;
+               goto err_busy;
        }
        *pvirqfd = virqfd;
 
        init_waitqueue_func_entry(&virqfd->wait, virqfd_wakeup);
        init_poll_funcptr(&virqfd->pt, virqfd_ptable_queue_proc);
 
-       events = file->f_op->poll(file, &virqfd->pt);
+       events = irqfd.file->f_op->poll(irqfd.file, &virqfd->pt);
 
        /*
         * Check if there was an event already pending on the eventfd
         * Do not drop the file until the irqfd is fully initialized,
         * otherwise we might race against the POLLHUP.
         */
-       fput(file);
+       fdput(irqfd);
 
        return 0;
-
-fail:
-       if (ctx && !IS_ERR(ctx))
-               eventfd_ctx_put(ctx);
-
-       if (file && !IS_ERR(file))
-               fput(file);
-
+err_busy:
+       eventfd_ctx_put(ctx);
+err_ctx:
+       fdput(irqfd);
+err_fd:
        kfree(virqfd);
 
        return ret;