Commit 59b701b9 authored by Mike Christie's avatar Mike Christie Committed by Michael S. Tsirkin

vhost-scsi: Use system wq to flush dev for TMFs

We flush all the workers that are not also used by the ctl vq to make
sure that responses queued by LIO before the TMF response are sent
before the TMF response. This requires a special vhost_vq_flush
function which, in the next patches where we handle SIGKILL killing
workers while in use, will require extra locking/complexity. To avoid
that, this patch has us flush the entire device from the system work
queue, then queue up sending the response from there.

This is a little less optimal since we now flush all workers but this
will be ok since commands have already timed out and perf is not a
concern.
Signed-off-by: default avatarMike Christie <michael.christie@oracle.com>
Message-Id: <20240316004707.45557-4-michael.christie@oracle.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 1eceddee
...@@ -210,6 +210,7 @@ struct vhost_scsi { ...@@ -210,6 +210,7 @@ struct vhost_scsi {
struct vhost_scsi_tmf { struct vhost_scsi_tmf {
struct vhost_work vwork; struct vhost_work vwork;
struct work_struct flush_work;
struct vhost_scsi *vhost; struct vhost_scsi *vhost;
struct vhost_scsi_virtqueue *svq; struct vhost_scsi_virtqueue *svq;
...@@ -373,9 +374,8 @@ static void vhost_scsi_release_cmd(struct se_cmd *se_cmd) ...@@ -373,9 +374,8 @@ static void vhost_scsi_release_cmd(struct se_cmd *se_cmd)
if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) { if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) {
struct vhost_scsi_tmf *tmf = container_of(se_cmd, struct vhost_scsi_tmf *tmf = container_of(se_cmd,
struct vhost_scsi_tmf, se_cmd); struct vhost_scsi_tmf, se_cmd);
struct vhost_virtqueue *vq = &tmf->svq->vq;
vhost_vq_work_queue(vq, &tmf->vwork); schedule_work(&tmf->flush_work);
} else { } else {
struct vhost_scsi_cmd *cmd = container_of(se_cmd, struct vhost_scsi_cmd *cmd = container_of(se_cmd,
struct vhost_scsi_cmd, tvc_se_cmd); struct vhost_scsi_cmd, tvc_se_cmd);
...@@ -1287,33 +1287,31 @@ static void vhost_scsi_tmf_resp_work(struct vhost_work *work) ...@@ -1287,33 +1287,31 @@ static void vhost_scsi_tmf_resp_work(struct vhost_work *work)
{ {
struct vhost_scsi_tmf *tmf = container_of(work, struct vhost_scsi_tmf, struct vhost_scsi_tmf *tmf = container_of(work, struct vhost_scsi_tmf,
vwork); vwork);
struct vhost_virtqueue *ctl_vq, *vq; int resp_code;
int resp_code, i;
if (tmf->scsi_resp == TMR_FUNCTION_COMPLETE) {
/*
* Flush IO vqs that don't share a worker with the ctl to make
* sure they have sent their responses before us.
*/
ctl_vq = &tmf->vhost->vqs[VHOST_SCSI_VQ_CTL].vq;
for (i = VHOST_SCSI_VQ_IO; i < tmf->vhost->dev.nvqs; i++) {
vq = &tmf->vhost->vqs[i].vq;
if (vhost_vq_is_setup(vq) &&
vq->worker != ctl_vq->worker)
vhost_vq_flush(vq);
}
if (tmf->scsi_resp == TMR_FUNCTION_COMPLETE)
resp_code = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED; resp_code = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
} else { else
resp_code = VIRTIO_SCSI_S_FUNCTION_REJECTED; resp_code = VIRTIO_SCSI_S_FUNCTION_REJECTED;
}
vhost_scsi_send_tmf_resp(tmf->vhost, &tmf->svq->vq, tmf->in_iovs, vhost_scsi_send_tmf_resp(tmf->vhost, &tmf->svq->vq, tmf->in_iovs,
tmf->vq_desc, &tmf->resp_iov, resp_code); tmf->vq_desc, &tmf->resp_iov, resp_code);
vhost_scsi_release_tmf_res(tmf); vhost_scsi_release_tmf_res(tmf);
} }
static void vhost_scsi_tmf_flush_work(struct work_struct *work)
{
struct vhost_scsi_tmf *tmf = container_of(work, struct vhost_scsi_tmf,
flush_work);
struct vhost_virtqueue *vq = &tmf->svq->vq;
/*
* Make sure we have sent responses for other commands before we
* send our response.
*/
vhost_dev_flush(vq->dev);
vhost_vq_work_queue(vq, &tmf->vwork);
}
static void static void
vhost_scsi_handle_tmf(struct vhost_scsi *vs, struct vhost_scsi_tpg *tpg, vhost_scsi_handle_tmf(struct vhost_scsi *vs, struct vhost_scsi_tpg *tpg,
struct vhost_virtqueue *vq, struct vhost_virtqueue *vq,
...@@ -1337,6 +1335,7 @@ vhost_scsi_handle_tmf(struct vhost_scsi *vs, struct vhost_scsi_tpg *tpg, ...@@ -1337,6 +1335,7 @@ vhost_scsi_handle_tmf(struct vhost_scsi *vs, struct vhost_scsi_tpg *tpg,
if (!tmf) if (!tmf)
goto send_reject; goto send_reject;
INIT_WORK(&tmf->flush_work, vhost_scsi_tmf_flush_work);
vhost_work_init(&tmf->vwork, vhost_scsi_tmf_resp_work); vhost_work_init(&tmf->vwork, vhost_scsi_tmf_resp_work);
tmf->vhost = vs; tmf->vhost = vs;
tmf->svq = svq; tmf->svq = svq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment