static void qemu_aio_complete(void *opaque, int ret) { struct ioreq *ioreq = opaque; if (ret != 0) { xen_be_printf(&ioreq->blkdev->xendev, 0, "%s I/O error\n", ioreq->req.operation == BLKIF_OP_READ ? "read" : "write"); ioreq->aio_errors++; } ioreq->aio_inflight--; if (ioreq->presync) { ioreq->presync = 0; ioreq_runio_qemu_aio(ioreq); return; } if (ioreq->aio_inflight > 0) { return; } if (ioreq->postsync) { ioreq->postsync = 0; ioreq->aio_inflight++; bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq); return; } ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; ioreq_unmap(ioreq); ioreq_finish(ioreq); bdrv_acct_done(ioreq->blkdev->bs, &ioreq->acct); qemu_bh_schedule(ioreq->blkdev->bh); }
static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, int is_read) { BlockErrorAction action = bdrv_get_on_error(req->dev->bs, is_read); VirtIOBlock *s = req->dev; if (action == BLOCK_ERR_IGNORE) { bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_IGNORE, is_read); return 0; } if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC) || action == BLOCK_ERR_STOP_ANY) { req->next = s->rq; s->rq = req; bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_STOP, is_read); vm_stop(RUN_STATE_IO_ERROR); bdrv_iostatus_set_err(s->bs, error); } else { virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); bdrv_acct_done(s->bs, &req->acct); g_free(req); bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_REPORT, is_read); } return 1; }
static void virtio_blk_flush_complete(void *opaque, int ret) { VirtIOBlockReq *req = opaque; if (ret) { if (virtio_blk_handle_rw_error(req, -ret, 0)) { return; } } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); bdrv_acct_done(req->dev->bs, &req->acct); virtio_blk_free_request(req); }
static void virtio_blk_rw_complete(void *opaque, int ret) { VirtIOBlockReq *req = opaque; trace_virtio_blk_rw_complete(req, ret); if (ret) { int is_read = !(ldl_p(&req->out->type) & VIRTIO_BLK_T_OUT); if (virtio_blk_handle_rw_error(req, -ret, is_read)) return; } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); bdrv_acct_done(req->dev->bs, &req->acct); g_free(req); }
static void virtio_blk_rw_complete(void *opaque, int ret) { VirtIOBlockReq *req = opaque; trace_virtio_blk_rw_complete(req, ret); if (ret) { int p = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type); bool is_read = !(p & VIRTIO_BLK_T_OUT); if (virtio_blk_handle_rw_error(req, -ret, is_read)) return; } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); bdrv_acct_done(req->dev->bs, &req->acct); virtio_blk_free_request(req); }
static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, bool is_read) { BlockErrorAction action = bdrv_get_error_action(req->dev->bs, is_read, error); VirtIOBlock *s = req->dev; if (action == BLOCK_ERROR_ACTION_STOP) { req->next = s->rq; s->rq = req; } else if (action == BLOCK_ERROR_ACTION_REPORT) { virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); bdrv_acct_done(s->bs, &req->acct); virtio_blk_free_request(req); } bdrv_error_action(s->bs, action, is_read, error); return action != BLOCK_ERROR_ACTION_IGNORE; }