struct iovec iov;
QEMUIOVector qiov;
BlockAcctCookie acct;
- unsigned char *status;
+ uint32_t status;
} SCSIDiskReq;
#define SCSI_DISK_F_REMOVABLE 0
return true;
}
- if (ret < 0 || (r->status && *r->status)) {
+ if (ret < 0 || r->status) {
return scsi_handle_rw_error(r, -ret, acct_failed);
}
* whether the error has to be handled by the guest or should rather
* pause the host.
*/
- assert(r->status && *r->status);
- if (scsi_sense_buf_is_guest_recoverable(r->req.sense, sizeof(r->req.sense))) {
+ assert(r->status);
+ if ((r->status >> 8) ||
+ scsi_sense_buf_is_guest_recoverable(r->req.sense, sizeof(r->req.sense))) {
/* These errors are handled by guest. */
sdc->update_sense(&r->req);
- scsi_req_complete(&r->req, *r->status);
+ scsi_req_complete(&r->req, r->status);
return true;
}
error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense));
/* CDB passed to SG_IO. */
uint8_t cdb[16];
+ BlockCompletionFunc *cb;
+ void *cb_opaque;
} SCSIBlockReq;
+static void sgio_aio_complete(void *opaque, int ret)
+{
+ SCSIBlockReq *req = (SCSIBlockReq *)opaque;
+ SCSIDiskReq *r = &req->req;
+ SCSISense sense;
+
+ trace_scsi_disk_aio_sgio_done(r->req.tag, ret, req->io_header.status,
+ req->io_header.host_status);
+ r->status = sg_io_sense_from_errno(-ret, &req->io_header, &sense);
+ if ((r->status & 0xff) == CHECK_CONDITION &&
+ req->io_header.status != CHECK_CONDITION)
+ scsi_req_build_sense(&r->req, sense);
+
+ req->cb(req->cb_opaque, ret);
+}
+
static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req,
int64_t offset, QEMUIOVector *iov,
int direction,
io_header->timeout = 5000;
io_header->usr_ptr = r;
io_header->flags |= SG_FLAG_DIRECT_IO;
+
+ req->cb = cb;
+ req->cb_opaque = opaque;
+
trace_scsi_disk_aio_sgio_command(r->req.tag, req->cdb[0], lba,
nb_logical_blocks, io_header->timeout);
- aiocb = blk_aio_ioctl(s->qdev.conf.blk, SG_IO, io_header, cb, opaque);
+ aiocb = blk_aio_ioctl(s->qdev.conf.blk, SG_IO, io_header,
+ sgio_aio_complete, req);
assert(aiocb != NULL);
return aiocb;
}
return 0;
}
- r->req.status = &r->io_header.status;
return scsi_disk_dma_command(req, buf);
}
scsi_disk_dma_command_WRITE(const char *cmd, uint64_t lba, int len) "Write %s(sector %" PRId64 ", count %u)"
scsi_disk_new_request(uint32_t lun, uint32_t tag, const char *line) "Command: lun=%d tag=0x%x data=%s"
scsi_disk_aio_sgio_command(uint32_t tag, uint8_t cmd, uint64_t lba, int len, uint32_t timeout) "disk aio sgio: tag=0x%x cmd 0x%x (sector %" PRId64 ", count %d) timeout %u"
+scsi_disk_aio_sgio_done(uint32_t tag, int ret, uint8_t status, uint8_t host_status) "disk aio sgio: cmd 0x%x ret %d status 0x%x host_status 0x%x"
# scsi-generic.c
scsi_generic_command_complete_noio(void *req, uint32_t tag, uint8_t status, uint8_t host_status) "Command complete %p tag=0x%x status=0x%x host_status=0x%x"