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; }
BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs, BlockdevOnError on_err, int is_read, int error) { BlockErrorAction action; switch (on_err) { case BLOCKDEV_ON_ERROR_ENOSPC: action = (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT; break; case BLOCKDEV_ON_ERROR_STOP: action = BDRV_ACTION_STOP; break; case BLOCKDEV_ON_ERROR_REPORT: action = BDRV_ACTION_REPORT; break; case BLOCKDEV_ON_ERROR_IGNORE: action = BDRV_ACTION_IGNORE; break; default: abort(); } bdrv_emit_qmp_error_event(job->bs, QEVENT_BLOCK_JOB_ERROR, action, is_read); if (action == BDRV_ACTION_STOP) { block_job_pause(job); block_job_iostatus_set_err(job, error); if (bs != job->bs) { bdrv_iostatus_set_err(bs, error); } } return action; }
BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs, BlockdevOnError on_err, int is_read, int error) { BlockErrorAction action; switch (on_err) { case BLOCKDEV_ON_ERROR_ENOSPC: action = (error == ENOSPC) ? BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT; break; case BLOCKDEV_ON_ERROR_STOP: action = BLOCK_ERROR_ACTION_STOP; break; case BLOCKDEV_ON_ERROR_REPORT: action = BLOCK_ERROR_ACTION_REPORT; break; case BLOCKDEV_ON_ERROR_IGNORE: action = BLOCK_ERROR_ACTION_IGNORE; break; default: abort(); } qapi_event_send_block_job_error(bdrv_get_device_name(job->bs), is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE, action, &error_abort); if (action == BLOCK_ERROR_ACTION_STOP) { /* make the pause user visible, which will be resumed from QMP. */ job->user_paused = true; block_job_pause(job); block_job_iostatus_set_err(job, error); if (bs != job->bs) { bdrv_iostatus_set_err(bs, error); } } return action; }