scsi-disk: introduce scsi_disk_req_check_error
Commonize all the checks for canceled requests and errors. The next patch will add another case to check for, in order to handle passthrough commands. There is no semantic change here; the only nontrivial modification is in scsi_write_do_fua, where cancellation has been checked earlier by both callers. Thus, the check is replaced with an assertion. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
94f8ba1125
commit
5b956f415a
|
@ -176,6 +176,20 @@ static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
|
||||||
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
|
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed)
|
||||||
|
{
|
||||||
|
if (r->req.io_canceled) {
|
||||||
|
scsi_req_cancel_complete(&r->req);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
return scsi_handle_rw_error(r, -ret, acct_failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void scsi_aio_complete(void *opaque, int ret)
|
static void scsi_aio_complete(void *opaque, int ret)
|
||||||
{
|
{
|
||||||
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
|
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
|
||||||
|
@ -183,17 +197,10 @@ static void scsi_aio_complete(void *opaque, int ret)
|
||||||
|
|
||||||
assert(r->req.aiocb != NULL);
|
assert(r->req.aiocb != NULL);
|
||||||
r->req.aiocb = NULL;
|
r->req.aiocb = NULL;
|
||||||
if (r->req.io_canceled) {
|
if (scsi_disk_req_check_error(r, ret, true)) {
|
||||||
scsi_req_cancel_complete(&r->req);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
if (scsi_handle_rw_error(r, -ret, true)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
|
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
|
||||||
scsi_req_complete(&r->req, GOOD);
|
scsi_req_complete(&r->req, GOOD);
|
||||||
|
|
||||||
|
@ -232,11 +239,7 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
|
||||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
||||||
|
|
||||||
assert(r->req.aiocb == NULL);
|
assert(r->req.aiocb == NULL);
|
||||||
|
assert(!r->req.io_canceled);
|
||||||
if (r->req.io_canceled) {
|
|
||||||
scsi_req_cancel_complete(&r->req);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r->need_fua_emulation) {
|
if (r->need_fua_emulation) {
|
||||||
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, 0,
|
block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct, 0,
|
||||||
|
@ -246,26 +249,16 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
|
||||||
}
|
}
|
||||||
|
|
||||||
scsi_req_complete(&r->req, GOOD);
|
scsi_req_complete(&r->req, GOOD);
|
||||||
|
|
||||||
done:
|
|
||||||
scsi_req_unref(&r->req);
|
scsi_req_unref(&r->req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scsi_dma_complete_noio(SCSIDiskReq *r, int ret)
|
static void scsi_dma_complete_noio(SCSIDiskReq *r, int ret)
|
||||||
{
|
{
|
||||||
assert(r->req.aiocb == NULL);
|
assert(r->req.aiocb == NULL);
|
||||||
|
if (scsi_disk_req_check_error(r, ret, false)) {
|
||||||
if (r->req.io_canceled) {
|
|
||||||
scsi_req_cancel_complete(&r->req);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
if (scsi_handle_rw_error(r, -ret, false)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r->sector += r->sector_count;
|
r->sector += r->sector_count;
|
||||||
r->sector_count = 0;
|
r->sector_count = 0;
|
||||||
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
|
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
|
||||||
|
@ -303,17 +296,10 @@ static void scsi_read_complete(void * opaque, int ret)
|
||||||
|
|
||||||
assert(r->req.aiocb != NULL);
|
assert(r->req.aiocb != NULL);
|
||||||
r->req.aiocb = NULL;
|
r->req.aiocb = NULL;
|
||||||
if (r->req.io_canceled) {
|
if (scsi_disk_req_check_error(r, ret, true)) {
|
||||||
scsi_req_cancel_complete(&r->req);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
if (scsi_handle_rw_error(r, -ret, true)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
|
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
|
||||||
DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
|
DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
|
||||||
|
|
||||||
|
@ -333,18 +319,10 @@ static void scsi_do_read(SCSIDiskReq *r, int ret)
|
||||||
SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
|
SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
|
||||||
|
|
||||||
assert (r->req.aiocb == NULL);
|
assert (r->req.aiocb == NULL);
|
||||||
|
if (scsi_disk_req_check_error(r, ret, false)) {
|
||||||
if (r->req.io_canceled) {
|
|
||||||
scsi_req_cancel_complete(&r->req);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
if (scsi_handle_rw_error(r, -ret, false)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The request is used as the AIO opaque value, so add a ref. */
|
/* The request is used as the AIO opaque value, so add a ref. */
|
||||||
scsi_req_ref(&r->req);
|
scsi_req_ref(&r->req);
|
||||||
|
|
||||||
|
@ -472,18 +450,10 @@ static void scsi_write_complete_noio(SCSIDiskReq *r, int ret)
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
|
|
||||||
assert (r->req.aiocb == NULL);
|
assert (r->req.aiocb == NULL);
|
||||||
|
if (scsi_disk_req_check_error(r, ret, false)) {
|
||||||
if (r->req.io_canceled) {
|
|
||||||
scsi_req_cancel_complete(&r->req);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
if (scsi_handle_rw_error(r, -ret, false)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
n = r->qiov.size / 512;
|
n = r->qiov.size / 512;
|
||||||
r->sector += n;
|
r->sector += n;
|
||||||
r->sector_count -= n;
|
r->sector_count -= n;
|
||||||
|
@ -1617,18 +1587,10 @@ static void scsi_unmap_complete_noio(UnmapCBData *data, int ret)
|
||||||
uint32_t nb_sectors;
|
uint32_t nb_sectors;
|
||||||
|
|
||||||
assert(r->req.aiocb == NULL);
|
assert(r->req.aiocb == NULL);
|
||||||
|
if (scsi_disk_req_check_error(r, ret, false)) {
|
||||||
if (r->req.io_canceled) {
|
|
||||||
scsi_req_cancel_complete(&r->req);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
if (scsi_handle_rw_error(r, -ret, false)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data->count > 0) {
|
if (data->count > 0) {
|
||||||
sector_num = ldq_be_p(&data->inbuf[0]);
|
sector_num = ldq_be_p(&data->inbuf[0]);
|
||||||
nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL;
|
nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL;
|
||||||
|
@ -1728,17 +1690,10 @@ static void scsi_write_same_complete(void *opaque, int ret)
|
||||||
|
|
||||||
assert(r->req.aiocb != NULL);
|
assert(r->req.aiocb != NULL);
|
||||||
r->req.aiocb = NULL;
|
r->req.aiocb = NULL;
|
||||||
if (r->req.io_canceled) {
|
if (scsi_disk_req_check_error(r, ret, true)) {
|
||||||
scsi_req_cancel_complete(&r->req);
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
if (scsi_handle_rw_error(r, -ret, true)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
|
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
|
||||||
|
|
||||||
data->nb_sectors -= data->iov.iov_len / 512;
|
data->nb_sectors -= data->iov.iov_len / 512;
|
||||||
|
|
Loading…
Reference in a new issue