static void virtio_blk_rw_complete(void *opaque, int ret) { VirtIOBlockReq *next = opaque; while (next) { VirtIOBlockReq *req = next; next = req->mr_next; trace_virtio_blk_rw_complete(req, ret); if (req->qiov.nalloc != -1) { /* If nalloc is != 1 req->qiov is a local copy of the original * external iovec. It was allocated in submit_merged_requests * to be able to merge requests. */ qemu_iovec_destroy(&req->qiov); } 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)) { continue; } } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); block_acct_done(blk_get_stats(req->dev->blk), &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); }
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 = !(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); qemu_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 void virtio_blk_rw_complete(void *opaque, int ret) { VirtIOBlockReq *next = opaque; while (next) { VirtIOBlockReq *req = next; next = req->mr_next; trace_virtio_blk_rw_complete(req, ret); if (req->qiov.nalloc != -1) { /* If nalloc is != 1 req->qiov is a local copy of the original * external iovec. It was allocated in submit_merged_requests * to be able to merge requests. */ qemu_iovec_destroy(&req->qiov); } if (ret) { int p = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type); bool is_read = !(p & VIRTIO_BLK_T_OUT); /* Note that memory may be dirtied on read failure. If the * virtio request is not completed here, as is the case for * BLOCK_ERROR_ACTION_STOP, the memory may not be copied * correctly during live migration. While this is ugly, * it is acceptable because the device is free to write to * the memory until the request is completed (which will * happen on the other side of the migration). */ if (virtio_blk_handle_rw_error(req, -ret, is_read)) { /* Break the link in case the next request is added to the * restart queue and is going to be parsed from the ring again. */ req->mr_next = NULL; continue; } } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); block_acct_done(blk_get_stats(req->dev->blk), &req->acct); virtio_blk_free_request(req); } }
static void virtio_blk_rw_complete(void *opaque, int ret) { VirtIOBlockReq *next = opaque; VirtIOBlock *s = next->dev; VirtIODevice *vdev = VIRTIO_DEVICE(s); aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); while (next) { VirtIOBlockReq *req = next; next = req->mr_next; trace_virtio_blk_rw_complete(vdev, req, ret); if (req->qiov.nalloc != -1) { /* If nalloc is != -1 req->qiov is a local copy of the original * external iovec. It was allocated in submit_requests to be * able to merge requests. */ qemu_iovec_destroy(&req->qiov); } if (ret) { int p = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type); bool is_read = !(p & VIRTIO_BLK_T_OUT); /* Note that memory may be dirtied on read failure. If the * virtio request is not completed here, as is the case for * BLOCK_ERROR_ACTION_STOP, the memory may not be copied * correctly during live migration. While this is ugly, * it is acceptable because the device is free to write to * the memory until the request is completed (which will * happen on the other side of the migration). */ if (virtio_blk_handle_rw_error(req, -ret, is_read, true)) { continue; } } virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); block_acct_done(blk_get_stats(req->dev->blk), &req->acct); virtio_blk_free_request(req); } aio_context_release(blk_get_aio_context(s->conf.conf.blk)); }