> From: Nicolin Chen <nicolinc@xxxxxxxxxx> > Sent: Friday, July 28, 2023 4:25 AM > > +static int iommufd_access_change_ioas(struct iommufd_access *access, > + struct iommufd_ioas *new_ioas) > +{ > + u32 iopt_access_list_id = access->iopt_access_list_id; > + struct iommufd_ioas *cur_ioas = access->ioas; > + int rc; > + > + lockdep_assert_held(&access->ioas_lock); > + > + /* We are racing with a concurrent detach, bail */ > + if (cur_ioas != access->ioas_unpin) > + return -EBUSY; > + > + if (IS_ERR(new_ioas)) > + return PTR_ERR(new_ioas); iommufd_access_change_ioas_id() already checks errors. > + > void iommufd_access_destroy_object(struct iommufd_object *obj) > { > struct iommufd_access *access = > container_of(obj, struct iommufd_access, obj); > > - if (access->ioas) { > - iopt_remove_access(&access->ioas->iopt, access, > - access->iopt_access_list_id); > - refcount_dec(&access->ioas->obj.users); > - access->ioas = NULL; > - } > + mutex_lock(&access->ioas_lock); > + if (access->ioas) > + WARN_ON(iommufd_access_change_ioas(access, NULL)); > + mutex_unlock(&access->ioas_lock); > iommufd_ctx_put(access->ictx); > } this changes the behavior of destroy. Previously it always removes the access w/o detecting race while now it will give up and throw out a warning. While I'm fine with this change from bisec p.o.v. it might be good to split this into a separate patch. > void iommufd_access_detach(struct iommufd_access *access) > { > - struct iommufd_ioas *cur_ioas = access->ioas; > + int rc; > > mutex_lock(&access->ioas_lock); > - if (WARN_ON(!access->ioas)) > - goto out; > - /* > - * 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) { > + if (WARN_ON(!access->ioas)) { > mutex_unlock(&access->ioas_lock); > - access->ops->unmap(access->data, 0, ULONG_MAX); > - mutex_lock(&access->ioas_lock); > + return; > } > - iopt_remove_access(&cur_ioas->iopt, access, > - access->iopt_access_list_id); > - refcount_dec(&cur_ioas->obj.users); > -out: > - access->ioas_unpin = NULL; > + rc = iommufd_access_change_ioas(access, NULL); > + WARN_ON(rc); 'rc' can be removed. Just "WARN_ON(iommufd_access_change_ioas(access, NULL));" otherwise looks good to me, Reviewed-by: Kevin Tian <kevin.tian@xxxxxxxxx>