aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michael.christie@oracle.com>2023-06-26 18:22:51 -0500
committerMichael S. Tsirkin <mst@redhat.com>2023-07-03 12:15:13 -0400
commit3e11c6eb6ab07de36cde49594e16fed044bf276e (patch)
tree8bf6a115a61128a7a3981b26f8b75f67598ee7df
parent3845308fc8b0bc6a9345df4f69ef56f9adc52218 (diff)
downloadnet-next-3e11c6eb6ab07de36cde49594e16fed044bf276e.tar.gz
vhost: create worker at end of vhost_dev_set_owner
vsock can start queueing work after VHOST_VSOCK_SET_GUEST_CID, so after we have called vhost_worker_create it can be calling vhost_work_queue and trying to access the vhost worker/task. If vhost_dev_alloc_iovecs fails, then vhost_worker_free could free the worker/task from under vsock. This moves vhost_worker_create to the end of vhost_dev_set_owner where we know we can no longer fail in that path. If it fails after the VHOST_SET_OWNER and userspace closes the device, then the normal vsock release handling will do the right thing. Signed-off-by: Mike Christie <michael.christie@oracle.com> Message-Id: <20230626232307.97930-2-michael.christie@oracle.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--drivers/vhost/vhost.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 60c9ebd629dd15..82966ffb4a5c25 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -572,20 +572,27 @@ long vhost_dev_set_owner(struct vhost_dev *dev)
vhost_attach_mm(dev);
+ err = vhost_dev_alloc_iovecs(dev);
+ if (err)
+ goto err_iovecs;
+
if (dev->use_worker) {
+ /*
+ * This should be done last, because vsock can queue work
+ * before VHOST_SET_OWNER so it simplifies the failure path
+ * below since we don't have to worry about vsock queueing
+ * while we free the worker.
+ */
err = vhost_worker_create(dev);
if (err)
goto err_worker;
}
- err = vhost_dev_alloc_iovecs(dev);
- if (err)
- goto err_iovecs;
-
return 0;
-err_iovecs:
- vhost_worker_free(dev);
+
err_worker:
+ vhost_dev_free_iovecs(dev);
+err_iovecs:
vhost_detach_mm(dev);
err_mm:
return err;