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 void blk_handle_requests(struct XenBlkDev *blkdev) { RING_IDX rc, rp; struct ioreq *ioreq; blkdev->more_work = 0; rc = blkdev->rings.common.req_cons; rp = blkdev->rings.common.sring->req_prod; xen_rmb(); /* Ensure we see queued requests up to 'rp'. */ blk_send_response_all(blkdev); while (rc != rp) { /* pull request from ring */ if (RING_REQUEST_CONS_OVERFLOW(&blkdev->rings.common, rc)) { break; } ioreq = ioreq_start(blkdev); if (ioreq == NULL) { blkdev->more_work++; break; } blk_get_request(blkdev, ioreq, rc); blkdev->rings.common.req_cons = ++rc; /* parse them */ if (ioreq_parse(ioreq) != 0) { switch (ioreq->req.operation) { case BLKIF_OP_READ: block_acct_invalid(blk_get_stats(blkdev->blk), BLOCK_ACCT_READ); break; case BLKIF_OP_WRITE: block_acct_invalid(blk_get_stats(blkdev->blk), BLOCK_ACCT_WRITE); break; case BLKIF_OP_FLUSH_DISKCACHE: block_acct_invalid(blk_get_stats(blkdev->blk), BLOCK_ACCT_FLUSH); default: break; }; if (blk_send_response_one(ioreq)) { xen_pv_send_notify(&blkdev->xendev); } ioreq_release(ioreq, false); continue; } ioreq_runio_qemu_aio(ioreq); } if (blkdev->more_work && blkdev->requests_inflight < blkdev->max_requests) { qemu_bh_schedule(blkdev->bh); } }
static void blk_handle_requests(struct XenBlkDev *blkdev) { RING_IDX rc, rp; struct ioreq *ioreq; blkdev->more_work = 0; rc = blkdev->rings.common.req_cons; rp = blkdev->rings.common.sring->req_prod; xen_rmb(); /* Ensure we see queued requests up to 'rp'. */ if (use_aio) { blk_send_response_all(blkdev); } while (rc != rp) { /* pull request from ring */ if (RING_REQUEST_CONS_OVERFLOW(&blkdev->rings.common, rc)) { break; } ioreq = ioreq_start(blkdev); if (ioreq == NULL) { blkdev->more_work++; break; } blk_get_request(blkdev, ioreq, rc); blkdev->rings.common.req_cons = ++rc; /* parse them */ if (ioreq_parse(ioreq) != 0) { if (blk_send_response_one(ioreq)) { xen_be_send_notify(&blkdev->xendev); } ioreq_release(ioreq); continue; } if (use_aio) { /* run i/o in aio mode */ ioreq_runio_qemu_aio(ioreq); } else { /* run i/o in sync mode */ ioreq_runio_qemu_sync(ioreq); } } if (!use_aio) { blk_send_response_all(blkdev); } if (blkdev->more_work && blkdev->requests_inflight < max_requests) { qemu_bh_schedule(blkdev->bh); } }
static void qemu_aio_complete(void *opaque, int ret) { struct ioreq *ioreq = opaque; struct XenBlkDev *blkdev = ioreq->blkdev; struct XenDevice *xendev = &blkdev->xendev; aio_context_acquire(blkdev->ctx); if (ret != 0) { xen_pv_printf(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); goto done; } if (ioreq->aio_inflight > 0) { goto done; } switch (ioreq->req.operation) { case BLKIF_OP_READ: /* in case of failure ioreq->aio_errors is increased */ if (ret == 0) { ioreq_grant_copy(ioreq); } qemu_vfree(ioreq->buf); break; case BLKIF_OP_WRITE: case BLKIF_OP_FLUSH_DISKCACHE: if (!ioreq->req.nr_segments) { break; } qemu_vfree(ioreq->buf); break; default: break; } ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; ioreq_finish(ioreq); switch (ioreq->req.operation) { case BLKIF_OP_WRITE: case BLKIF_OP_FLUSH_DISKCACHE: if (!ioreq->req.nr_segments) { break; } case BLKIF_OP_READ: if (ioreq->status == BLKIF_RSP_OKAY) { block_acct_done(blk_get_stats(blkdev->blk), &ioreq->acct); } else { block_acct_failed(blk_get_stats(blkdev->blk), &ioreq->acct); } break; case BLKIF_OP_DISCARD: default: break; } qemu_bh_schedule(blkdev->bh); done: aio_context_release(blkdev->ctx); }