Skip to content

Commit 3ca5166

Browse files
mikechristiemstsirkin
authored andcommitted
vhost-scsi: Add better resource allocation failure handling
If we can't allocate mem to map in data for a request or can't find a tag for a command, we currently drop the command. This leads to the error handler running to clean it up. Instead of dropping the command this has us return an error telling the initiator that it queued more commands than we can handle. The initiator will then reduce how many commands it will send us and retry later. Signed-off-by: Mike Christie <michael.christie@oracle.com> Message-Id: <20241203191705.19431-4-michael.christie@oracle.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
1 parent bf2d650 commit 3ca5166

File tree

1 file changed

+25
-3
lines changed

1 file changed

+25
-3
lines changed

drivers/vhost/scsi.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ vhost_scsi_get_cmd(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
629629

630630
tag = sbitmap_get(&svq->scsi_tags);
631631
if (tag < 0) {
632-
pr_err("Unable to obtain tag for vhost_scsi_cmd\n");
632+
pr_warn_once("Guest sent too many cmds. Returning TASK_SET_FULL.\n");
633633
return ERR_PTR(-ENOMEM);
634634
}
635635

@@ -928,6 +928,24 @@ static void vhost_scsi_target_queue_cmd(struct vhost_scsi_cmd *cmd)
928928
target_submit(se_cmd);
929929
}
930930

931+
static void
932+
vhost_scsi_send_status(struct vhost_scsi *vs, struct vhost_virtqueue *vq,
933+
int head, unsigned int out, u8 status)
934+
{
935+
struct virtio_scsi_cmd_resp __user *resp;
936+
struct virtio_scsi_cmd_resp rsp;
937+
int ret;
938+
939+
memset(&rsp, 0, sizeof(rsp));
940+
rsp.status = status;
941+
resp = vq->iov[out].iov_base;
942+
ret = __copy_to_user(resp, &rsp, sizeof(rsp));
943+
if (!ret)
944+
vhost_add_used_and_signal(&vs->dev, vq, head, 0);
945+
else
946+
pr_err("Faulted on virtio_scsi_cmd_resp\n");
947+
}
948+
931949
static void
932950
vhost_scsi_send_bad_target(struct vhost_scsi *vs,
933951
struct vhost_virtqueue *vq,
@@ -1215,8 +1233,8 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
12151233
exp_data_len + prot_bytes,
12161234
data_direction);
12171235
if (IS_ERR(cmd)) {
1218-
vq_err(vq, "vhost_scsi_get_cmd failed %ld\n",
1219-
PTR_ERR(cmd));
1236+
ret = PTR_ERR(cmd);
1237+
vq_err(vq, "vhost_scsi_get_tag failed %dd\n", ret);
12201238
goto err;
12211239
}
12221240
cmd->tvc_vhost = vs;
@@ -1253,11 +1271,15 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
12531271
* EINVAL: Invalid response buffer, drop the request
12541272
* EIO: Respond with bad target
12551273
* EAGAIN: Pending request
1274+
* ENOMEM: Could not allocate resources for request
12561275
*/
12571276
if (ret == -ENXIO)
12581277
break;
12591278
else if (ret == -EIO)
12601279
vhost_scsi_send_bad_target(vs, vq, vc.head, vc.out);
1280+
else if (ret == -ENOMEM)
1281+
vhost_scsi_send_status(vs, vq, vc.head, vc.out,
1282+
SAM_STAT_TASK_SET_FULL);
12611283
} while (likely(!vhost_exceeds_weight(vq, ++c, 0)));
12621284
out:
12631285
mutex_unlock(&vq->mutex);

0 commit comments

Comments
 (0)