From: Leon Romanovsky <leonro@nvidia.com>
DMABUF ->pin() interface is called when the DMABUF importer perform
its DMA mapping, so let's use this opportunity to check if DMABUF
exporter revoked its buffer or not.
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
drivers/vfio/pci/vfio_pci_dmabuf.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c
index d4d0f7d08c53..af9c315ddf71 100644
--- a/drivers/vfio/pci/vfio_pci_dmabuf.c
+++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
@@ -20,6 +20,20 @@ struct vfio_pci_dma_buf {
u8 revoked : 1;
};
+static int vfio_pci_dma_buf_pin(struct dma_buf_attachment *attachment)
+{
+ struct vfio_pci_dma_buf *priv = attachment->dmabuf->priv;
+
+ dma_resv_assert_held(priv->dmabuf->resv);
+
+ return dma_buf_attachment_is_revoke(attachment) ? 0 : -EOPNOTSUPP;
+}
+
+static void vfio_pci_dma_buf_unpin(struct dma_buf_attachment *attachment)
+{
+ /* Do nothing */
+}
+
static int vfio_pci_dma_buf_attach(struct dma_buf *dmabuf,
struct dma_buf_attachment *attachment)
{
@@ -76,6 +90,8 @@ static void vfio_pci_dma_buf_release(struct dma_buf *dmabuf)
}
static const struct dma_buf_ops vfio_pci_dmabuf_ops = {
+ .pin = vfio_pci_dma_buf_pin,
+ .unpin = vfio_pci_dma_buf_unpin,
.attach = vfio_pci_dma_buf_attach,
.map_dma_buf = vfio_pci_dma_buf_map,
.unmap_dma_buf = vfio_pci_dma_buf_unmap,
--
2.52.0
On 1/18/26 13:08, Leon Romanovsky wrote:
> From: Leon Romanovsky <leonro@nvidia.com>
>
> DMABUF ->pin() interface is called when the DMABUF importer perform
> its DMA mapping, so let's use this opportunity to check if DMABUF
> exporter revoked its buffer or not.
>
> Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
> ---
> drivers/vfio/pci/vfio_pci_dmabuf.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c
> index d4d0f7d08c53..af9c315ddf71 100644
> --- a/drivers/vfio/pci/vfio_pci_dmabuf.c
> +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
> @@ -20,6 +20,20 @@ struct vfio_pci_dma_buf {
> u8 revoked : 1;
> };
>
> +static int vfio_pci_dma_buf_pin(struct dma_buf_attachment *attachment)
> +{
> + struct vfio_pci_dma_buf *priv = attachment->dmabuf->priv;
> +
> + dma_resv_assert_held(priv->dmabuf->resv);
> +
> + return dma_buf_attachment_is_revoke(attachment) ? 0 : -EOPNOTSUPP;
It's probably better to do that check in vfio_pci_dma_buf_attach.
And BTW the function vfio_pci_dma_buf_move() seems to be broken:
void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked)
{
struct vfio_pci_dma_buf *priv;
struct vfio_pci_dma_buf *tmp;
lockdep_assert_held_write(&vdev->memory_lock);
list_for_each_entry_safe(priv, tmp, &vdev->dmabufs, dmabufs_elm) {
if (!get_file_active(&priv->dmabuf->file))
continue;
if (priv->revoked != revoked) {
dma_resv_lock(priv->dmabuf->resv, NULL);
priv->revoked = revoked;
dma_buf_move_notify(priv->dmabuf);
A dma_buf_move_notify() just triggers asynchronous invalidation of the mapping!
You need to use dma_resv_wait() to wait for that to finish.
dma_resv_unlock(priv->dmabuf->resv);
}
fput(priv->dmabuf->file);
}
}
Regards,
Christian.
> +}
> +
> +static void vfio_pci_dma_buf_unpin(struct dma_buf_attachment *attachment)
> +{
> + /* Do nothing */
> +}
> +
> static int vfio_pci_dma_buf_attach(struct dma_buf *dmabuf,
> struct dma_buf_attachment *attachment)
> {
> @@ -76,6 +90,8 @@ static void vfio_pci_dma_buf_release(struct dma_buf *dmabuf)
> }
>
> static const struct dma_buf_ops vfio_pci_dmabuf_ops = {
> + .pin = vfio_pci_dma_buf_pin,
> + .unpin = vfio_pci_dma_buf_unpin,
> .attach = vfio_pci_dma_buf_attach,
> .map_dma_buf = vfio_pci_dma_buf_map,
> .unmap_dma_buf = vfio_pci_dma_buf_unmap,
>
On Mon, Jan 19, 2026 at 01:12:45PM +0100, Christian König wrote:
> On 1/18/26 13:08, Leon Romanovsky wrote:
> > From: Leon Romanovsky <leonro@nvidia.com>
> >
> > DMABUF ->pin() interface is called when the DMABUF importer perform
> > its DMA mapping, so let's use this opportunity to check if DMABUF
> > exporter revoked its buffer or not.
> >
> > Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
> > ---
> > drivers/vfio/pci/vfio_pci_dmabuf.c | 16 ++++++++++++++++
> > 1 file changed, 16 insertions(+)
> >
> > diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c
> > index d4d0f7d08c53..af9c315ddf71 100644
> > --- a/drivers/vfio/pci/vfio_pci_dmabuf.c
> > +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
> > @@ -20,6 +20,20 @@ struct vfio_pci_dma_buf {
> > u8 revoked : 1;
> > };
> >
> > +static int vfio_pci_dma_buf_pin(struct dma_buf_attachment *attachment)
> > +{
> > + struct vfio_pci_dma_buf *priv = attachment->dmabuf->priv;
> > +
> > + dma_resv_assert_held(priv->dmabuf->resv);
> > +
> > + return dma_buf_attachment_is_revoke(attachment) ? 0 : -EOPNOTSUPP;
>
> It's probably better to do that check in vfio_pci_dma_buf_attach.
I assume you are proposing to add this check in both
vfio_pci_dma_buf_attach() and vfio_pci_dma_buf_pin(). Otherwise,
importers that lack .invalidate_mapping() will invoke dma_buf_pin()
and will not fail.
>
> And BTW the function vfio_pci_dma_buf_move() seems to be broken:
>
> void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked)
> {
> struct vfio_pci_dma_buf *priv;
> struct vfio_pci_dma_buf *tmp;
>
> lockdep_assert_held_write(&vdev->memory_lock);
>
> list_for_each_entry_safe(priv, tmp, &vdev->dmabufs, dmabufs_elm) {
> if (!get_file_active(&priv->dmabuf->file))
> continue;
>
> if (priv->revoked != revoked) {
> dma_resv_lock(priv->dmabuf->resv, NULL);
> priv->revoked = revoked;
> dma_buf_move_notify(priv->dmabuf);
>
> A dma_buf_move_notify() just triggers asynchronous invalidation of the mapping!
>
> You need to use dma_resv_wait() to wait for that to finish.
We (VFIO and IOMMUFD) followed the same pattern used in
amdgpu_bo_move_notify(), which also does not wait.
I'll add wait here.
Thanks
>
> dma_resv_unlock(priv->dmabuf->resv);
> }
> fput(priv->dmabuf->file);
> }
> }
>
> Regards,
> Christian.
>
>
> > +}
> > +
> > +static void vfio_pci_dma_buf_unpin(struct dma_buf_attachment *attachment)
> > +{
> > + /* Do nothing */
> > +}
> > +
> > static int vfio_pci_dma_buf_attach(struct dma_buf *dmabuf,
> > struct dma_buf_attachment *attachment)
> > {
> > @@ -76,6 +90,8 @@ static void vfio_pci_dma_buf_release(struct dma_buf *dmabuf)
> > }
> >
> > static const struct dma_buf_ops vfio_pci_dmabuf_ops = {
> > + .pin = vfio_pci_dma_buf_pin,
> > + .unpin = vfio_pci_dma_buf_unpin,
> > .attach = vfio_pci_dma_buf_attach,
> > .map_dma_buf = vfio_pci_dma_buf_map,
> > .unmap_dma_buf = vfio_pci_dma_buf_unmap,
> >
>
On Mon, Jan 19, 2026 at 03:02:44PM +0200, Leon Romanovsky wrote: > We (VFIO and IOMMUFD) followed the same pattern used in > amdgpu_bo_move_notify(), which also does not wait. You have to be really careful copying anything from the GPU drivers as they have these waits hidden and batched in other parts of their operations.. Jason
On 1/19/26 14:02, Leon Romanovsky wrote:
> On Mon, Jan 19, 2026 at 01:12:45PM +0100, Christian König wrote:
>> On 1/18/26 13:08, Leon Romanovsky wrote:
>>> From: Leon Romanovsky <leonro@nvidia.com>
>>>
>>> DMABUF ->pin() interface is called when the DMABUF importer perform
>>> its DMA mapping, so let's use this opportunity to check if DMABUF
>>> exporter revoked its buffer or not.
>>>
>>> Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
>>> ---
>>> drivers/vfio/pci/vfio_pci_dmabuf.c | 16 ++++++++++++++++
>>> 1 file changed, 16 insertions(+)
>>>
>>> diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c
>>> index d4d0f7d08c53..af9c315ddf71 100644
>>> --- a/drivers/vfio/pci/vfio_pci_dmabuf.c
>>> +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
>>> @@ -20,6 +20,20 @@ struct vfio_pci_dma_buf {
>>> u8 revoked : 1;
>>> };
>>>
>>> +static int vfio_pci_dma_buf_pin(struct dma_buf_attachment *attachment)
>>> +{
>>> + struct vfio_pci_dma_buf *priv = attachment->dmabuf->priv;
>>> +
>>> + dma_resv_assert_held(priv->dmabuf->resv);
>>> +
>>> + return dma_buf_attachment_is_revoke(attachment) ? 0 : -EOPNOTSUPP;
>>
>> It's probably better to do that check in vfio_pci_dma_buf_attach.
>
> I assume you are proposing to add this check in both
> vfio_pci_dma_buf_attach() and vfio_pci_dma_buf_pin(). Otherwise,
> importers that lack .invalidate_mapping() will invoke dma_buf_pin()
> and will not fail.
vfio_pci_dma_buf_attach() alone should be sufficient. It is always called, even for importers lacking invalidate_mapping().
Regards,
Christian.
>
>>
>> And BTW the function vfio_pci_dma_buf_move() seems to be broken:
>>
>> void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked)
>> {
>> struct vfio_pci_dma_buf *priv;
>> struct vfio_pci_dma_buf *tmp;
>>
>> lockdep_assert_held_write(&vdev->memory_lock);
>>
>> list_for_each_entry_safe(priv, tmp, &vdev->dmabufs, dmabufs_elm) {
>> if (!get_file_active(&priv->dmabuf->file))
>> continue;
>>
>> if (priv->revoked != revoked) {
>> dma_resv_lock(priv->dmabuf->resv, NULL);
>> priv->revoked = revoked;
>> dma_buf_move_notify(priv->dmabuf);
>>
>> A dma_buf_move_notify() just triggers asynchronous invalidation of the mapping!
>>
>> You need to use dma_resv_wait() to wait for that to finish.
>
> We (VFIO and IOMMUFD) followed the same pattern used in
> amdgpu_bo_move_notify(), which also does not wait.
>
> I'll add wait here.
>
> Thanks
>
>>
>> dma_resv_unlock(priv->dmabuf->resv);
>> }
>> fput(priv->dmabuf->file);
>> }
>> }
>>
>> Regards,
>> Christian.
>>
>>
>>> +}
>>> +
>>> +static void vfio_pci_dma_buf_unpin(struct dma_buf_attachment *attachment)
>>> +{
>>> + /* Do nothing */
>>> +}
>>> +
>>> static int vfio_pci_dma_buf_attach(struct dma_buf *dmabuf,
>>> struct dma_buf_attachment *attachment)
>>> {
>>> @@ -76,6 +90,8 @@ static void vfio_pci_dma_buf_release(struct dma_buf *dmabuf)
>>> }
>>>
>>> static const struct dma_buf_ops vfio_pci_dmabuf_ops = {
>>> + .pin = vfio_pci_dma_buf_pin,
>>> + .unpin = vfio_pci_dma_buf_unpin,
>>> .attach = vfio_pci_dma_buf_attach,
>>> .map_dma_buf = vfio_pci_dma_buf_map,
>>> .unmap_dma_buf = vfio_pci_dma_buf_unmap,
>>>
>>
© 2016 - 2026 Red Hat, Inc.