[PATCH] vdpa/vdpa_sim: guard partial device teardown

Xiong Weimin <[email protected]> Tue, 4 Aug 2026 15:36:41 +0800
Newsgroups dev.linux.lists.virtualization,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
vdpasim_create() unwinds early allocation failures with put_device(),
which invokes the vdpa free callback even when the worker, virtqueues or
IOTLB arrays have not all been initialized.  vdpasim_free() currently
assumes the fully initialized path and can dereference NULL or ERR_PTR
state during those failures.

Make the free callback tolerate partially initialized simulator devices
before destroying the worker or walking optional arrays.

Signed-off-by: Xiong Weimin <[email protected]>
---
 drivers/vdpa/vdpa_sim/vdpa_sim.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
index 8cb1cc2ea..77966e957 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
@@ -743,17 +743,22 @@ static void vdpasim_free(struct vdpa_device *vdpa)
 	int i;
 
 	kthread_cancel_work_sync(&vdpasim->work);
-	kthread_destroy_worker(vdpasim->worker);
+	if (!IS_ERR_OR_NULL(vdpasim->worker))
+		kthread_destroy_worker(vdpasim->worker);
 
-	for (i = 0; i < vdpasim->dev_attr.nvqs; i++) {
-		vringh_kiov_cleanup(&vdpasim->vqs[i].out_iov);
-		vringh_kiov_cleanup(&vdpasim->vqs[i].in_iov);
+	if (vdpasim->vqs) {
+		for (i = 0; i < vdpasim->dev_attr.nvqs; i++) {
+			vringh_kiov_cleanup(&vdpasim->vqs[i].out_iov);
+			vringh_kiov_cleanup(&vdpasim->vqs[i].in_iov);
+		}
 	}
 
 	vdpasim->dev_attr.free(vdpasim);
 
-	for (i = 0; i < vdpasim->dev_attr.nas; i++)
-		vhost_iotlb_reset(&vdpasim->iommu[i]);
+	if (vdpasim->iommu) {
+		for (i = 0; i < vdpasim->dev_attr.nas; i++)
+			vhost_iotlb_reset(&vdpasim->iommu[i]);
+	}
 	kfree(vdpasim->iommu);
 	kfree(vdpasim->iommu_pt);
 	kfree(vdpasim->vqs);
-- 
2.43.0