On Tue, 6 Oct 2026 20:36:37 +0100
Matt Evans <[email protected]> wrote:
> +#ifdef CONFIG_VFIO_PCI_DMABUF
> +int vfio_pci_core_feature_dma_buf_revoke(
> + struct vfio_pci_core_device *vdev, u32 flags,
> + struct vfio_device_feature_dma_buf_revoke __user *arg,
> + size_t argsz)
> +{
> + struct vfio_device_feature_dma_buf_revoke db_revoke;
> + struct vfio_pci_dma_buf *priv;
> + struct dma_buf *dmabuf;
> + int ret;
> +
> + if (!vdev->pci_ops || !vdev->pci_ops->get_dmabuf_phys)
> + return -EOPNOTSUPP;
> +
> + ret = vfio_check_feature(flags, argsz,
> + VFIO_DEVICE_FEATURE_SET,
> + sizeof(db_revoke));
> + if (ret != 1)
> + return ret;
> +
> + if (copy_from_user(&db_revoke, arg, sizeof(db_revoke)))
> + return -EFAULT;
> +
> + dmabuf = dma_buf_get(db_revoke.dmabuf_fd);
> + if (IS_ERR(dmabuf))
> + return PTR_ERR(dmabuf);
> +
> + priv = dmabuf->priv;
> + /*
> + * Sanity-check the DMABUF is really a vfio_pci_dma_buf _and_
> + * relates to the VFIO device it was provided with.
> + *
> + * If the DMABUF relates to this vdev then priv->vdev is
> + * stable because this open fd prevents cleanup.
> + *
> + * If it relates to a different vdev, reading priv->vdev might
> + * race with a concurrent cleanup on that device. But if so,
> + * it points to a non-matching vdev or NULL and is unusable
> + * either way.
> + */
> + if (dmabuf->ops != &vfio_pci_dmabuf_ops ||
> + READ_ONCE(priv->vdev) != vdev) {
> + ret = -ENODEV;
> + goto out_put_buf;
> + }
> +
> + /*
> + * memory_lock(R) is taken to stop vfio_pci_dev_set_hot_reset()
> + * from getting it and then blocking all devices in the dev_set behind
> + * this revoke's drain.
> + */
> + down_read(&vdev->memory_lock);
> + down_write(&vdev->dmabuf_lock);
> + if (priv->status == VFIO_PCI_DMABUF_DEAD) {
> + ret = -EBADFD;
Kind of ugly to special case the condition in the caller that's already
tested in the function. Why not return an errno for this purpose?
Thanks,
Alex
> + } else {
> + vfio_pci_dma_buf_set_status(priv, VFIO_PCI_DMABUF_DEAD);
> + ret = 0;
> + }
> + up_write(&vdev->dmabuf_lock);
> + up_read(&vdev->memory_lock);
> +
> +out_put_buf:
> + dma_buf_put(dmabuf);
> +
> + return ret;
> +}
> +#endif /* CONFIG_VFIO_PCI_DMABUF */