From: Jason Gunthorpe <jgg@nvidia.com>
To: "Tian, Kevin" <kevin.tian@intel.com>
Cc: Xu Yilun <yilun.xu@linux.intel.com>,
"will@kernel.org" <will@kernel.org>,
"aneesh.kumar@kernel.org" <aneesh.kumar@kernel.org>,
"iommu@lists.linux.dev" <iommu@lists.linux.dev>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"joro@8bytes.org" <joro@8bytes.org>,
"robin.murphy@arm.com" <robin.murphy@arm.com>,
"shuah@kernel.org" <shuah@kernel.org>,
"nicolinc@nvidia.com" <nicolinc@nvidia.com>,
"aik@amd.com" <aik@amd.com>,
"Williams, Dan J" <dan.j.williams@intel.com>,
"baolu.lu@linux.intel.com" <baolu.lu@linux.intel.com>,
"Xu, Yilun" <yilun.xu@intel.com>
Subject: Re: [PATCH v3 2/5] iommufd: Destroy vdevice on idevice destroy
Date: Wed, 2 Jul 2025 09:40:42 -0300 [thread overview]
Message-ID: <20250702124042.GD1051729@nvidia.com> (raw)
In-Reply-To: <BN9PR11MB52769790C63FFCDC711E80DB8C40A@BN9PR11MB5276.namprd11.prod.outlook.com>
On Wed, Jul 02, 2025 at 09:13:50AM +0000, Tian, Kevin wrote:
> > > Yes, you can't touch idev inside the destroy function at all, under
> > > any version. idev is only valid if you have a refcount on vdev.
> > >
> > > But why are you touching this lock? Arrange things so abort doesn't
> > > touch the idev??
> >
> > idev has a pointer idev->vdev to track the vdev's lifecycle.
> > idev->igroup->lock protects the pointer. At the end of
> > iommufd_vdevice_destroy() this pointer should be NULLed so that idev
> > knows vdev is really destroyed.
Well, that is destroy, not abort, but OK, there is an issue with
destroy.
> but comparing to that I'd prefer to the original wait approach...
Okay, but lets try to keep the wait hidden inside the refcounting..
The issue here is we don't hold a refcount on idev while working with
idev. Let's fix that and then things should work properly?
Maybe something like this:
diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index 4e781aa9fc6329..9174fa7c972b80 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -178,12 +178,20 @@ static void iommufd_device_remove_vdev(struct iommufd_device *idev)
mutex_unlock(&idev->igroup->lock);
}
+void iommufd_device_pre_destroy(struct iommufd_object *obj)
+{
+ struct iommufd_device *idev =
+ container_of(obj, struct iommufd_device, obj);
+
+ /* Release the short term users on this */
+ iommufd_device_remove_vdev(idev);
+}
+
void iommufd_device_destroy(struct iommufd_object *obj)
{
struct iommufd_device *idev =
container_of(obj, struct iommufd_device, obj);
- iommufd_device_remove_vdev(idev);
iommu_device_release_dma_owner(idev->dev);
iommufd_put_group(idev->igroup);
if (!iommufd_selftest_is_mock_dev(idev->dev))
diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c
index b2e8e106c16158..387c630fdabfbd 100644
--- a/drivers/iommu/iommufd/main.c
+++ b/drivers/iommu/iommufd/main.c
@@ -151,6 +151,9 @@ static int iommufd_object_dec_wait_shortterm(struct iommufd_ctx *ictx,
if (refcount_dec_and_test(&to_destroy->shortterm_users))
return 0;
+ if (iommufd_object_ops[to_destroy->type].pre_destroy)
+ iommufd_object_ops[to_destroy->type].pre_destroy(to_destroy);
+
if (wait_event_timeout(ictx->destroy_wait,
refcount_read(&to_destroy->shortterm_users) == 0,
msecs_to_jiffies(60000)))
@@ -567,6 +570,7 @@ static const struct iommufd_object_ops iommufd_object_ops[] = {
.destroy = iommufd_access_destroy_object,
},
[IOMMUFD_OBJ_DEVICE] = {
+ .pre_destroy = iommufd_device_pre_destroy,
.destroy = iommufd_device_destroy,
},
[IOMMUFD_OBJ_FAULT] = {
diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c
index 9451a311745f7b..cbf99daa7dc25d 100644
--- a/drivers/iommu/iommufd/viommu.c
+++ b/drivers/iommu/iommufd/viommu.c
@@ -135,6 +135,7 @@ void iommufd_vdevice_destroy(struct iommufd_object *obj)
mutex_lock(&vdev->idev->igroup->lock);
iommufd_vdevice_abort(obj);
mutex_unlock(&vdev->idev->igroup->lock);
+ iommufd_put_object(vdev->viommu->ictx, &vdev->idev->obj);
}
int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd)
@@ -180,13 +181,19 @@ int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd)
vdev->id = virt_id;
vdev->viommu = viommu;
refcount_inc(&viommu->obj.users);
+
+ /*
+ * A reference is held on the idev so long as we have a pointer.
+ * iommufd_device_pre_destroy() will revoke it before the real
+ * destruction.
+ */
+ vdev->idev = idev;
+
/*
* iommufd_device_destroy() waits until idev->vdev is NULL before
* freeing the idev, which only happens once the vdev is finished
- * destruction. Thus we do not need refcounting on either idev->vdev or
- * vdev->idev.
+ * destruction.
*/
- vdev->idev = idev;
idev->vdev = vdev;
curr = xa_cmpxchg(&viommu->vdevs, virt_id, NULL, vdev, GFP_KERNEL);
@@ -207,7 +214,8 @@ int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd)
out_unlock_igroup:
mutex_unlock(&idev->igroup->lock);
out_put_idev:
- iommufd_put_object(ucmd->ictx, &idev->obj);
+ if (rc)
+ iommufd_put_object(ucmd->ictx, &idev->obj);
out_put_viommu:
iommufd_put_object(ucmd->ictx, &viommu->obj);
return rc;
next prev parent reply other threads:[~2025-07-02 12:40 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-27 3:38 [PATCH v3 0/5] iommufd: Destroy vdevice on device unbind Xu Yilun
2025-06-27 3:38 ` [PATCH v3 1/5] iommufd: Add iommufd_object_tombstone_user() helper Xu Yilun
2025-06-30 3:08 ` Baolu Lu
2025-06-30 7:24 ` Xu Yilun
2025-06-30 5:52 ` Tian, Kevin
2025-06-30 6:41 ` Xu Yilun
2025-06-30 19:50 ` Nicolin Chen
2025-07-08 8:45 ` Xu Yilun
2025-06-27 3:38 ` [PATCH v3 2/5] iommufd: Destroy vdevice on idevice destroy Xu Yilun
2025-06-30 5:08 ` Baolu Lu
2025-07-08 8:34 ` Xu Yilun
2025-06-30 6:27 ` Tian, Kevin
2025-06-30 10:18 ` Xu Yilun
2025-06-30 14:50 ` Jason Gunthorpe
2025-07-01 9:19 ` Xu Yilun
2025-07-01 12:13 ` Jason Gunthorpe
2025-07-02 2:23 ` Xu Yilun
2025-07-02 9:13 ` Tian, Kevin
2025-07-02 12:40 ` Jason Gunthorpe [this message]
2025-07-03 4:32 ` Tian, Kevin
2025-07-03 11:21 ` Jason Gunthorpe
2025-07-07 10:58 ` Xu Yilun
2025-07-07 12:25 ` Jason Gunthorpe
2025-07-07 19:41 ` Xu Yilun
2025-06-30 19:34 ` Nicolin Chen
2025-07-08 8:12 ` Xu Yilun
2025-06-27 3:38 ` [PATCH v3 3/5] iommufd/vdevice: Remove struct device reference from struct vdevice Xu Yilun
2025-06-30 5:11 ` Baolu Lu
2025-07-04 15:06 ` Jason Gunthorpe
2025-06-27 3:38 ` [PATCH v3 4/5] iommufd/selftest: Explicitly skip tests for inapplicable variant Xu Yilun
2025-07-04 15:07 ` Jason Gunthorpe
2025-06-27 3:38 ` [PATCH v3 5/5] iommufd/selftest: Add coverage for vdevice tombstone Xu Yilun
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250702124042.GD1051729@nvidia.com \
--to=jgg@nvidia.com \
--cc=aik@amd.com \
--cc=aneesh.kumar@kernel.org \
--cc=baolu.lu@linux.intel.com \
--cc=dan.j.williams@intel.com \
--cc=iommu@lists.linux.dev \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=nicolinc@nvidia.com \
--cc=robin.murphy@arm.com \
--cc=shuah@kernel.org \
--cc=will@kernel.org \
--cc=yilun.xu@intel.com \
--cc=yilun.xu@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.