|
@@ -500,6 +500,51 @@ static void virtio_scsi_complete_cmd_req(VirtIOSCSIReq *req)
|
|
|
virtio_scsi_complete_req(req);
|
|
|
}
|
|
|
|
|
|
+static void virtio_scsi_command_failed(SCSIRequest *r)
|
|
|
+{
|
|
|
+ VirtIOSCSIReq *req = r->hba_private;
|
|
|
+
|
|
|
+ if (r->io_canceled) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ req->resp.cmd.status = GOOD;
|
|
|
+ switch (r->host_status) {
|
|
|
+ case SCSI_HOST_NO_LUN:
|
|
|
+ req->resp.cmd.response = VIRTIO_SCSI_S_INCORRECT_LUN;
|
|
|
+ break;
|
|
|
+ case SCSI_HOST_BUSY:
|
|
|
+ req->resp.cmd.response = VIRTIO_SCSI_S_BUSY;
|
|
|
+ break;
|
|
|
+ case SCSI_HOST_TIME_OUT:
|
|
|
+ case SCSI_HOST_ABORTED:
|
|
|
+ req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
|
|
|
+ break;
|
|
|
+ case SCSI_HOST_BAD_RESPONSE:
|
|
|
+ req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
|
|
|
+ break;
|
|
|
+ case SCSI_HOST_RESET:
|
|
|
+ req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
|
|
|
+ break;
|
|
|
+ case SCSI_HOST_TRANSPORT_DISRUPTED:
|
|
|
+ req->resp.cmd.response = VIRTIO_SCSI_S_TRANSPORT_FAILURE;
|
|
|
+ break;
|
|
|
+ case SCSI_HOST_TARGET_FAILURE:
|
|
|
+ req->resp.cmd.response = VIRTIO_SCSI_S_TARGET_FAILURE;
|
|
|
+ break;
|
|
|
+ case SCSI_HOST_RESERVATION_ERROR:
|
|
|
+ req->resp.cmd.response = VIRTIO_SCSI_S_NEXUS_FAILURE;
|
|
|
+ break;
|
|
|
+ case SCSI_HOST_ALLOCATION_FAILURE:
|
|
|
+ case SCSI_HOST_MEDIUM_ERROR:
|
|
|
+ case SCSI_HOST_ERROR:
|
|
|
+ default:
|
|
|
+ req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ virtio_scsi_complete_cmd_req(req);
|
|
|
+}
|
|
|
+
|
|
|
static void virtio_scsi_command_complete(SCSIRequest *r, size_t resid)
|
|
|
{
|
|
|
VirtIOSCSIReq *req = r->hba_private;
|
|
@@ -908,6 +953,7 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
|
|
|
.max_lun = VIRTIO_SCSI_MAX_LUN,
|
|
|
|
|
|
.complete = virtio_scsi_command_complete,
|
|
|
+ .fail = virtio_scsi_command_failed,
|
|
|
.cancel = virtio_scsi_request_cancelled,
|
|
|
.change = virtio_scsi_change,
|
|
|
.parse_cdb = virtio_scsi_parse_cdb,
|