On Fri, Jun 23, 2023 at 11:15:40AM -0300, Jason Gunthorpe wrote: > > +static void __iommufd_access_detach(struct iommufd_access *access) > > +{ > > + struct iommufd_ioas *cur_ioas = access->ioas; > > + > > + lockdep_assert_held(&access->ioas_lock); > > + /* > > + * Set ioas to NULL to block any further iommufd_access_pin_pages(). > > + * iommufd_access_unpin_pages() can continue using access->ioas_unpin. > > + */ > > + access->ioas = NULL; > > + > > + if (access->ops->unmap) { > > + mutex_unlock(&access->ioas_lock); > > + access->ops->unmap(access->data, 0, ULONG_MAX); > > + mutex_lock(&access->ioas_lock); > > + } > > + iopt_remove_access(&cur_ioas->iopt, access); > > + refcount_dec(&cur_ioas->obj.users); > > +} > > + > > +void iommufd_access_detach(struct iommufd_access *access) > > +{ > > + mutex_lock(&access->ioas_lock); > > + if (WARN_ON(!access->ioas)) > > + goto out; > > + __iommufd_access_detach(access); > > +out: > > + access->ioas_unpin = NULL; > > + mutex_unlock(&access->ioas_lock); > > +} > > +EXPORT_SYMBOL_NS_GPL(iommufd_access_detach, IOMMUFD); > > There is not really any benefit to make this two functions The __iommufd_access_detach() will be used by replace() in the following series. Yet, let's merge them here then. And I'll add __iommufd_access_detach() back in the replace series. > > int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id) > > { > [..] > > if (access->ioas) { > > if (access->ioas || access->ioas_unpin) { Ack. > But I wonder if it should be a WARN_ON? Does VFIO protect against > the userspace racing detach and attach, or do we expect to do it here? VFIO has a vdev->iommufd_attached flag to prevent a double call of this function. And detach and attach there also have a mutex protection. So it should be a WARN_ON here, I think. > > @@ -579,8 +620,8 @@ void iommufd_access_notify_unmap(struct io_pagetable *iopt, unsigned long iova, > > void iommufd_access_unpin_pages(struct iommufd_access *access, > > unsigned long iova, unsigned long length) > > { > > - struct io_pagetable *iopt = &access->ioas->iopt; > > struct iopt_area_contig_iter iter; > > + struct io_pagetable *iopt; > > unsigned long last_iova; > > struct iopt_area *area; > > > > @@ -588,6 +629,13 @@ void iommufd_access_unpin_pages(struct iommufd_access *access, > > WARN_ON(check_add_overflow(iova, length - 1, &last_iova))) > > return; > > > > + mutex_lock(&access->ioas_lock); > > + if (!access->ioas_unpin) { > > This should be WARN_ON(), the driver has done something wrong if we > call this after the access has been detached. Ack. Also adding a line of comments for that: + /* + * The driver must be doing something wrong if it calls this before an + * iommufd_access_attach() or after an iommufd_access_detach(). + */ + if (WARN_ON(!access->ioas_unpin)) { Thanks Nic