On 2026-08-31T15:51:57+02:00, Hanna Czenczek <[email protected]> wrote:
> For latency alerts, we will want to generate QMP events from block
> accounting cookies. These should contain some minimal information about
> the offending request, i.e., start offset, size, and type. The latter
> two are already part of the cookie, the former is not. Add it.
>
> Signed-off-by: Hanna Czenczek <[email protected]>
> ---
> include/block/accounting.h | 7 ++++-
> include/system/dma.h | 2 +-
> block/accounting.c | 3 ++-
> hw/block/dataplane/xen-block.c | 4 +--
> hw/block/virtio-blk.c | 15 ++++++-----
> hw/ide/ahci.c | 6 +++--
> hw/ide/atapi.c | 9 ++++---
> hw/ide/core.c | 9 +++++--
> hw/ide/macio.c | 15 ++++++++---
> hw/nvme/ctrl.c | 43 +++++++++++++++++-------------
> hw/nvme/dif.c | 8 +++---
> hw/scsi/scsi-disk.c | 28 ++++++++++++-------
> qemu-io-cmds.c | 14 +++++-----
> system/dma-helpers.c | 4 +--
> tests/unit/test-block-accounting.c | 2 +-
> 15 files changed, 105 insertions(+), 64 deletions(-)
>
> diff --git a/include/block/accounting.h b/include/block/accounting.h
> index 12d32460927..9386440ec89 100644
> --- a/include/block/accounting.h
> +++ b/include/block/accounting.h
> @@ -95,6 +95,7 @@ struct BlockAcctStats {
> };
>
> typedef struct BlockAcctCookie {
> + int64_t offset;
> int64_t bytes;
> int64_t start_time_ns;
> enum BlockAcctType type;
> @@ -108,8 +109,12 @@ void block_acct_cleanup(BlockAcctStats *stats);
> void block_acct_add_interval(BlockAcctStats *stats, unsigned
> interval_length);
> BlockAcctTimedStats *block_acct_interval_next(BlockAcctStats *stats,
> BlockAcctTimedStats *s);
> +/**
> + * Begin an I/O operation.
> + * @offset == -1 indicates an unknown offset (e.g. for meta operations).
> + */
> void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie,
> - int64_t bytes, enum BlockAcctType type);
> + int64_t offset, int64_t bytes, enum BlockAcctType
> type);
> void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie);
> void block_acct_failed(BlockAcctStats *stats, BlockAcctCookie *cookie);
> void block_acct_invalid(BlockAcctStats *stats, enum BlockAcctType type);
> diff --git a/include/system/dma.h b/include/system/dma.h
> index 82e7ad54374..1291697642e 100644
> --- a/include/system/dma.h
> +++ b/include/system/dma.h
> @@ -305,7 +305,7 @@ MemTxResult dma_buf_write(void *ptr, dma_addr_t len,
> dma_addr_t *residual,
> QEMUSGList *sg, MemTxAttrs attrs);
>
> void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
> - QEMUSGList *sg, enum BlockAcctType type);
> + QEMUSGList *sg, int64_t offset, enum BlockAcctType type);
>
> /**
> * dma_aligned_pow2_mask: Return the address bit mask of the largest
> diff --git a/block/accounting.c b/block/accounting.c
> index 038af370170..66e5001403f 100644
> --- a/block/accounting.c
> +++ b/block/accounting.c
> @@ -115,10 +115,11 @@ BlockAcctTimedStats
> *block_acct_interval_next(BlockAcctStats *stats,
> }
>
> void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie,
> - int64_t bytes, enum BlockAcctType type)
> + int64_t offset, int64_t bytes, enum BlockAcctType type)
> {
> assert(type < BLOCK_MAX_IOTYPE);
>
> + cookie->offset = offset;
> cookie->bytes = bytes;
> cookie->start_time_ns = qemu_clock_get_ns(clock_type);
> cookie->type = type;
> diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
> index 48c2e315f31..f4dab9b2510 100644
> --- a/hw/block/dataplane/xen-block.c
> +++ b/hw/block/dataplane/xen-block.c
> @@ -373,7 +373,7 @@ static int xen_block_do_aio(XenBlockRequest *request)
> case BLKIF_OP_READ:
> qemu_iovec_add(&request->v, request->buf, request->size);
> block_acct_start(blk_get_stats(dataplane->blk), &request->acct,
> - request->v.size, BLOCK_ACCT_READ);
> + request->start, request->v.size, BLOCK_ACCT_READ);
> request->aio_inflight++;
> blk_aio_preadv(dataplane->blk, request->start, &request->v, 0,
> xen_block_complete_aio, request);
> @@ -386,7 +386,7 @@ static int xen_block_do_aio(XenBlockRequest *request)
>
> qemu_iovec_add(&request->v, request->buf, request->size);
> block_acct_start(blk_get_stats(dataplane->blk), &request->acct,
> - request->v.size,
> + request->start, request->v.size,
> request->req.operation == BLKIF_OP_WRITE ?
> BLOCK_ACCT_WRITE : BLOCK_ACCT_FLUSH);
> request->aio_inflight++;
> diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
> index 384a5ee3f1c..d2605814795 100644
> --- a/hw/block/virtio-blk.c
> +++ b/hw/block/virtio-blk.c
> @@ -338,7 +338,7 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req,
> MultiReqBuffer *mrb)
> {
> VirtIOBlock *s = req->dev;
>
> - block_acct_start(blk_get_stats(s->blk), &req->acct, 0,
> + block_acct_start(blk_get_stats(s->blk), &req->acct, -1, 0,
> BLOCK_ACCT_FLUSH);
>
> /*
> @@ -421,8 +421,8 @@ static uint8_t
> virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
> blk_aio_flags |= BDRV_REQ_MAY_UNMAP;
> }
>
> - block_acct_start(blk_get_stats(s->blk), &req->acct, bytes,
> - BLOCK_ACCT_WRITE);
> + block_acct_start(blk_get_stats(s->blk), &req->acct,
> + sector << BDRV_SECTOR_BITS, bytes,
> BLOCK_ACCT_WRITE);
>
> blk_aio_pwrite_zeroes(s->blk, sector << BDRV_SECTOR_BITS,
> bytes, blk_aio_flags,
> @@ -437,8 +437,8 @@ static uint8_t
> virtio_blk_handle_discard_write_zeroes(VirtIOBlockReq *req,
> goto err;
> }
>
> - block_acct_start(blk_get_stats(s->blk), &req->acct, bytes,
> - BLOCK_ACCT_UNMAP);
> + block_acct_start(blk_get_stats(s->blk), &req->acct,
> + sector << BDRV_SECTOR_BITS, bytes,
> BLOCK_ACCT_UNMAP);
>
> blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, bytes,
> virtio_blk_discard_write_zeroes_complete, req);
> @@ -813,7 +813,7 @@ static int virtio_blk_handle_zone_append(VirtIOBlockReq
> *req,
> data->zone_append_data.offset = offset;
> qemu_iovec_init_external(&req->qiov, out_iov, out_num);
>
> - block_acct_start(blk_get_stats(s->blk), &req->acct, len,
> + block_acct_start(blk_get_stats(s->blk), &req->acct, offset, len,
> BLOCK_ACCT_ZONE_APPEND);
>
> blk_aio_zone_append(s->blk, &data->zone_append_data.offset, &req->qiov,
> 0,
> @@ -893,7 +893,8 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req,
> MultiReqBuffer *mrb)
> return 0;
> }
>
> - block_acct_start(blk_get_stats(s->blk), &req->acct, req->qiov.size,
> + block_acct_start(blk_get_stats(s->blk), &req->acct,
> + req->sector_num * BDRV_SECTOR_SIZE, req->qiov.size,
> is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ);
>
> /* merge would exceed maximum number of requests or IO direction
> diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
> index 6b04762c4ad..cf63c87a013 100644
> --- a/hw/ide/ahci.c
> +++ b/hw/ide/ahci.c
> @@ -1092,7 +1092,8 @@ static void execute_ncq_command(NCQTransferState
> *ncq_tfs)
> trace_execute_ncq_command_read(ad->hba, port, ncq_tfs->tag,
> ncq_tfs->sector_count, ncq_tfs->lba);
> dma_acct_start(ide_state->blk, &ncq_tfs->acct,
> - &ncq_tfs->sglist, BLOCK_ACCT_READ);
> + &ncq_tfs->sglist, ncq_tfs->lba << BDRV_SECTOR_BITS,
> + BLOCK_ACCT_READ);
> ncq_tfs->aiocb = dma_blk_read(ide_state->blk, &ncq_tfs->sglist,
> ncq_tfs->lba << BDRV_SECTOR_BITS,
> BDRV_SECTOR_SIZE,
> @@ -1102,7 +1103,8 @@ static void execute_ncq_command(NCQTransferState
> *ncq_tfs)
> trace_execute_ncq_command_write(ad->hba, port, ncq_tfs->tag,
> ncq_tfs->sector_count, ncq_tfs->lba);
> dma_acct_start(ide_state->blk, &ncq_tfs->acct,
> - &ncq_tfs->sglist, BLOCK_ACCT_WRITE);
> + &ncq_tfs->sglist, ncq_tfs->lba << BDRV_SECTOR_BITS,
> + BLOCK_ACCT_WRITE);
> ncq_tfs->aiocb = dma_blk_write(ide_state->blk, &ncq_tfs->sglist,
> ncq_tfs->lba << BDRV_SECTOR_BITS,
> BDRV_SECTOR_SIZE,
> diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
> index 0ea149ad8c6..6f1187bce12 100644
> --- a/hw/ide/atapi.c
> +++ b/hw/ide/atapi.c
> @@ -163,6 +163,7 @@ static int cd_read_sector(IDEState *s)
> trace_cd_read_sector(s->lba);
>
> block_acct_start(blk_get_stats(s->blk), &s->acct,
> + (int64_t)s->lba << ATAPI_SECTOR_BITS,
> nsec * ATAPI_SECTOR_SIZE, BLOCK_ACCT_READ);
>
> ide_buffered_readv(s, (int64_t)s->lba << 2, &s->qiov, nsec * 4,
> @@ -297,7 +298,8 @@ static void ide_atapi_cmd_reply(IDEState *s, int size,
> int max_size)
> s->elementary_transfer_size = 0;
>
> if (s->atapi_dma) {
> - block_acct_start(blk_get_stats(s->blk), &s->acct, size,
> + /* No offset available for these commands */
> + block_acct_start(blk_get_stats(s->blk), &s->acct, -1, size,
> BLOCK_ACCT_READ);
> s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
> ide_start_dma(s, ide_atapi_cmd_read_dma_cb);
> @@ -419,8 +421,9 @@ static void ide_atapi_cmd_read_dma(IDEState *s, int lba,
> int nb_sectors,
> s->io_buffer_size = 0;
> s->cd_sector_size = sector_size;
>
> - block_acct_start(blk_get_stats(s->blk), &s->acct,
> s->packet_transfer_size,
> - BLOCK_ACCT_READ);
> + block_acct_start(blk_get_stats(s->blk), &s->acct,
> + (int64_t)lba << ATAPI_SECTOR_BITS,
> + s->packet_transfer_size, BLOCK_ACCT_READ);
>
> /* XXX: check if BUSY_STAT should be set */
> s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
> diff --git a/hw/ide/core.c b/hw/ide/core.c
> index 06e6bb6067d..4b559cf68d0 100644
> --- a/hw/ide/core.c
> +++ b/hw/ide/core.c
> @@ -491,6 +491,7 @@ static void coroutine_fn ide_trim_co_entry(void *opaque)
> }
>
> block_acct_start(blk_get_stats(s->blk), &s->acct,
> + sector << BDRV_SECTOR_BITS,
> count << BDRV_SECTOR_BITS, BLOCK_ACCT_UNMAP);
>
> /* Got an entry! Submit and exit. */
> @@ -833,6 +834,7 @@ static void ide_sector_read(IDEState *s)
> qemu_iovec_init_buf(&s->qiov, s->io_buffer, n * BDRV_SECTOR_SIZE);
>
> block_acct_start(blk_get_stats(s->blk), &s->acct,
> + sector_num << BDRV_SECTOR_BITS,
> n * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ);
> s->pio_aiocb = ide_buffered_readv(s, sector_num, &s->qiov, n,
> ide_sector_read_cb, s);
> @@ -1009,10 +1011,12 @@ static void ide_sector_start_dma(IDEState *s, enum
> ide_dma_cmd dma_cmd)
> switch (dma_cmd) {
> case IDE_DMA_READ:
> block_acct_start(blk_get_stats(s->blk), &s->acct,
> + ide_get_sector(s) << BDRV_SECTOR_BITS,
> s->nsector * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ);
> break;
> case IDE_DMA_WRITE:
> block_acct_start(blk_get_stats(s->blk), &s->acct,
> + ide_get_sector(s) << BDRV_SECTOR_BITS,
> s->nsector * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE);
> break;
> default:
> @@ -1112,7 +1116,8 @@ static void ide_sector_write(IDEState *s)
> qemu_iovec_init_buf(&s->qiov, s->io_buffer, n * BDRV_SECTOR_SIZE);
>
> block_acct_start(blk_get_stats(s->blk), &s->acct,
> - n * BDRV_SECTOR_SIZE, BLOCK_ACCT_WRITE);
> + sector_num << BDRV_SECTOR_BITS, n * BDRV_SECTOR_SIZE,
> + BLOCK_ACCT_WRITE);
> s->pio_aiocb = blk_aio_pwritev(s->blk, sector_num << BDRV_SECTOR_BITS,
> &s->qiov, 0, ide_sector_write_cb, s);
> }
> @@ -1147,7 +1152,7 @@ static void ide_flush_cache(IDEState *s)
>
> s->status |= BUSY_STAT;
> ide_set_retry(s);
> - block_acct_start(blk_get_stats(s->blk), &s->acct, 0, BLOCK_ACCT_FLUSH);
> + block_acct_start(blk_get_stats(s->blk), &s->acct, -1, 0,
> BLOCK_ACCT_FLUSH);
> s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s);
> }
>
> diff --git a/hw/ide/macio.c b/hw/ide/macio.c
> index 40fb4f3b4f3..99d079be916 100644
> --- a/hw/ide/macio.c
> +++ b/hw/ide/macio.c
> @@ -218,7 +218,14 @@ static void pmac_ide_transfer(DBDMA_io *io)
> MACIO_DPRINTF("\n");
>
> if (s->drive_kind == IDE_CD) {
> - block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
> + int64_t offset = -1;
> +
> + if (s->lba >= 0) {
> + /* Same hardcoded 11 as in pmac_ide_atapi_transfer_cb() */
> + offset = ((int64_t)s->lba << 11) + s->io_buffer_index;
> + }
> +
> + block_acct_start(blk_get_stats(s->blk), &s->acct, offset, io->len,
> BLOCK_ACCT_READ);
>
> pmac_ide_atapi_transfer_cb(io, 0);
> @@ -227,11 +234,13 @@ static void pmac_ide_transfer(DBDMA_io *io)
>
> switch (s->dma_cmd) {
> case IDE_DMA_READ:
> - block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
> + block_acct_start(blk_get_stats(s->blk), &s->acct,
> + ide_get_sector(s) << BDRV_SECTOR_BITS, io->len,
> BLOCK_ACCT_READ);
> break;
> case IDE_DMA_WRITE:
> - block_acct_start(blk_get_stats(s->blk), &s->acct, io->len,
> + block_acct_start(blk_get_stats(s->blk), &s->acct,
> + ide_get_sector(s) << BDRV_SECTOR_BITS, io->len,
> BLOCK_ACCT_WRITE);
> break;
> default:
> diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
> index 5168551e115..980816a2145 100644
> --- a/hw/nvme/ctrl.c
> +++ b/hw/nvme/ctrl.c
> @@ -2754,7 +2754,7 @@ static uint16_t nvme_verify(NvmeCtrl *n, NvmeRequest
> *req)
> qemu_iovec_init(&ctx->data.iov, 1);
> qemu_iovec_add(&ctx->data.iov, ctx->data.bounce, len);
>
> - block_acct_start(blk_get_stats(blk), &req->acct, ctx->data.iov.size,
> + block_acct_start(blk_get_stats(blk), &req->acct, offset,
> ctx->data.iov.size,
> BLOCK_ACCT_READ);
>
> req->aiocb = blk_aio_preadv(ns->blkconf.blk, offset, &ctx->data.iov, 0,
> @@ -2983,6 +2983,7 @@ static void nvme_copy_out_cb(void *opaque, int ret)
> uint32_t nlb;
> size_t mlen;
> uint8_t *mbounce;
> + int64_t offset;
>
> if (ret < 0 || iocb->ret < 0) {
> block_acct_failed(stats, &iocb->acct.write);
> @@ -3003,10 +3004,10 @@ static void nvme_copy_out_cb(void *opaque, int ret)
> qemu_iovec_reset(&iocb->iov);
> qemu_iovec_add(&iocb->iov, mbounce, mlen);
>
> - block_acct_start(stats, &iocb->acct.write, mlen, BLOCK_ACCT_WRITE);
> - iocb->aiocb = blk_aio_pwritev(dns->blkconf.blk, nvme_moff(dns,
> iocb->slba),
> - &iocb->iov, 0, nvme_copy_out_completed_cb,
> - iocb);
> + offset = nvme_moff(dns, iocb->slba);
> + block_acct_start(stats, &iocb->acct.write, offset, mlen,
> BLOCK_ACCT_WRITE);
> + iocb->aiocb = blk_aio_pwritev(dns->blkconf.blk, offset, &iocb->iov, 0,
> + nvme_copy_out_completed_cb, iocb);
>
> return;
>
> @@ -3029,6 +3030,7 @@ static void nvme_copy_in_completed_cb(void *opaque, int
> ret)
> uint64_t reftag;
> size_t len, mlen;
> uint16_t status;
> + int64_t offset;
>
> if (ret < 0) {
> iocb->ret = ret;
> @@ -3113,10 +3115,11 @@ static void nvme_copy_in_completed_cb(void *opaque,
> int ret)
> qemu_iovec_reset(&iocb->iov);
> qemu_iovec_add(&iocb->iov, iocb->bounce, len);
>
> - block_acct_start(blk_get_stats(dns->blkconf.blk), &iocb->acct.write, len,
> - BLOCK_ACCT_WRITE);
> + offset = nvme_l2b(dns, iocb->slba);
> + block_acct_start(blk_get_stats(dns->blkconf.blk), &iocb->acct.write,
> + offset, len, BLOCK_ACCT_WRITE);
>
> - iocb->aiocb = blk_aio_pwritev(dns->blkconf.blk, nvme_l2b(dns,
> iocb->slba),
> + iocb->aiocb = blk_aio_pwritev(dns->blkconf.blk, offset,
> &iocb->iov, 0, nvme_copy_out_cb, iocb);
>
> return;
> @@ -3136,6 +3139,7 @@ static void nvme_copy_in_cb(void *opaque, int ret)
> uint64_t slba;
> uint32_t nlb;
> size_t mlen;
> + int64_t offset;
>
> if (ret < 0 || iocb->ret < 0) {
> block_acct_failed(stats, &iocb->acct.read);
> @@ -3154,10 +3158,11 @@ static void nvme_copy_in_cb(void *opaque, int ret)
> qemu_iovec_reset(&iocb->iov);
> qemu_iovec_add(&iocb->iov, iocb->bounce + nvme_l2b(sns, nlb), mlen);
>
> - block_acct_start(stats, &iocb->acct.read, mlen, BLOCK_ACCT_READ);
> - iocb->aiocb = blk_aio_preadv(sns->blkconf.blk, nvme_moff(sns, slba),
> - &iocb->iov, 0, nvme_copy_in_completed_cb,
> - iocb);
> + offset = nvme_moff(sns, slba);
> + block_acct_start(stats, &iocb->acct.read, offset, mlen,
> + BLOCK_ACCT_READ);
> + iocb->aiocb = blk_aio_preadv(sns->blkconf.blk, offset, &iocb->iov, 0,
> + nvme_copy_in_completed_cb, iocb);
> return;
>
> out:
> @@ -3236,6 +3241,7 @@ static void nvme_do_copy(NvmeCopyAIOCB *iocb)
> uint16_t status;
> uint32_t dnsid = le32_to_cpu(req->cmd.nsid);
> uint32_t snsid = dnsid;
> + int64_t offset;
>
> if (iocb->ret < 0) {
> goto done;
> @@ -3362,10 +3368,11 @@ static void nvme_do_copy(NvmeCopyAIOCB *iocb)
> assert(len <= blen);
> qemu_iovec_add(&iocb->iov, iocb->bounce, len);
>
> - block_acct_start(blk_get_stats(sns->blkconf.blk), &iocb->acct.read, len,
> - BLOCK_ACCT_READ);
> + offset = nvme_l2b(sns, slba);
> + block_acct_start(blk_get_stats(sns->blkconf.blk), &iocb->acct.read,
> + offset, len, BLOCK_ACCT_READ);
>
> - iocb->aiocb = blk_aio_preadv(sns->blkconf.blk, nvme_l2b(sns, slba),
> + iocb->aiocb = blk_aio_preadv(sns->blkconf.blk, offset,
> &iocb->iov, 0, nvme_copy_in_cb, iocb);
> return;
>
> @@ -3524,7 +3531,7 @@ static uint16_t nvme_compare(NvmeCtrl *n, NvmeRequest
> *req)
> qemu_iovec_init(&ctx->data.iov, 1);
> qemu_iovec_add(&ctx->data.iov, ctx->data.bounce, data_len);
>
> - block_acct_start(blk_get_stats(blk), &req->acct, data_len,
> + block_acct_start(blk_get_stats(blk), &req->acct, offset, data_len,
> BLOCK_ACCT_READ);
> req->aiocb = blk_aio_preadv(blk, offset, &ctx->data.iov, 0,
> nvme_compare_data_cb, req);
> @@ -3722,7 +3729,7 @@ static uint16_t nvme_read(NvmeCtrl *n, NvmeRequest *req)
>
> data_offset = nvme_l2b(ns, slba);
>
> - block_acct_start(blk_get_stats(blk), &req->acct, data_size,
> + block_acct_start(blk_get_stats(blk), &req->acct, data_offset, data_size,
> BLOCK_ACCT_READ);
> nvme_blk_read(blk, data_offset, BDRV_SECTOR_SIZE, nvme_rw_cb, req);
> return NVME_NO_COMPLETE;
> @@ -3892,7 +3899,7 @@ static uint16_t nvme_do_write(NvmeCtrl *n, NvmeRequest
> *req, bool append,
> goto invalid;
> }
>
> - block_acct_start(blk_get_stats(blk), &req->acct, data_size,
> + block_acct_start(blk_get_stats(blk), &req->acct, data_offset,
> data_size,
> BLOCK_ACCT_WRITE);
> nvme_blk_write(blk, data_offset, BDRV_SECTOR_SIZE, nvme_rw_cb, req);
> } else {
> diff --git a/hw/nvme/dif.c b/hw/nvme/dif.c
> index 4e7874f3223..fbd4d8eb816 100644
> --- a/hw/nvme/dif.c
> +++ b/hw/nvme/dif.c
> @@ -644,8 +644,8 @@ uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req)
> qemu_iovec_add(&ctx->data.iov, ctx->data.bounce, len);
>
> if (req->cmd.opcode == NVME_CMD_READ) {
> - block_acct_start(blk_get_stats(blk), &req->acct, ctx->data.iov.size,
> - BLOCK_ACCT_READ);
> + block_acct_start(blk_get_stats(blk), &req->acct, offset,
> + ctx->data.iov.size, BLOCK_ACCT_READ);
>
> req->aiocb = blk_aio_preadv(ns->blkconf.blk, offset, &ctx->data.iov,
> 0,
> nvme_dif_rw_mdata_in_cb, ctx);
> @@ -690,8 +690,8 @@ uint16_t nvme_dif_rw(NvmeCtrl *n, NvmeRequest *req)
> }
> }
>
> - block_acct_start(blk_get_stats(blk), &req->acct, ctx->data.iov.size,
> - BLOCK_ACCT_WRITE);
> + block_acct_start(blk_get_stats(blk), &req->acct, offset,
> + ctx->data.iov.size, BLOCK_ACCT_WRITE);
>
> req->aiocb = blk_aio_pwritev(ns->blkconf.blk, offset, &ctx->data.iov, 0,
> nvme_dif_rw_mdata_out_cb, ctx);
> diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
> index 24bd1a78b6e..5b40e404e13 100644
> --- a/hw/scsi/scsi-disk.c
> +++ b/hw/scsi/scsi-disk.c
> @@ -484,7 +484,8 @@ static void scsi_do_read(SCSIDiskReq *r, int ret)
> scsi_req_ref(&r->req);
>
> if (r->req.sg) {
> - dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg,
> BLOCK_ACCT_READ);
> + dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg,
> + r->sector << BDRV_SECTOR_BITS, BLOCK_ACCT_READ);
> r->req.residual -= r->req.sg->size;
> r->req.aiocb = dma_blk_io(r->req.sg, r->sector << BDRV_SECTOR_BITS,
> BDRV_SECTOR_SIZE,
> @@ -493,7 +494,8 @@ static void scsi_do_read(SCSIDiskReq *r, int ret)
> } else {
> scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
> block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
> - r->qiov.size, BLOCK_ACCT_READ);
> + r->sector << BDRV_SECTOR_BITS, r->qiov.size,
> + BLOCK_ACCT_READ);
> r->req.aiocb = sdc->dma_readv(r->sector << BDRV_SECTOR_BITS,
> &r->qiov,
> scsi_read_complete, r, r);
> }
> @@ -551,7 +553,7 @@ static void scsi_read_data(SCSIRequest *req)
> first = !r->started;
> r->started = true;
> if (first && r->need_fua) {
> - 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, -1, 0,
> BLOCK_ACCT_FLUSH);
> r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_do_read_cb, r);
> } else {
> @@ -634,7 +636,7 @@ static void scsi_write_data(SCSIRequest *req)
>
> if (r->req.cmd.buf[0] == VERIFY_10 || r->req.cmd.buf[0] == VERIFY_12 ||
> r->req.cmd.buf[0] == VERIFY_16) {
> - 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, -1, 0,
> BLOCK_ACCT_FLUSH);
> cb = r->req.sg ? scsi_dma_complete : scsi_write_complete;
> r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, cb, r);
> @@ -642,7 +644,8 @@ static void scsi_write_data(SCSIRequest *req)
> }
>
> if (r->req.sg) {
> - dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg,
> BLOCK_ACCT_WRITE);
> + dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg,
> + r->sector << BDRV_SECTOR_BITS, BLOCK_ACCT_WRITE);
> r->req.residual -= r->req.sg->size;
> r->req.aiocb = dma_blk_io(r->req.sg, r->sector << BDRV_SECTOR_BITS,
> BDRV_SECTOR_SIZE,
> @@ -650,7 +653,8 @@ static void scsi_write_data(SCSIRequest *req)
> DMA_DIRECTION_TO_DEVICE);
> } else {
> block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
> - r->qiov.size, BLOCK_ACCT_WRITE);
> + r->sector << BDRV_SECTOR_BITS, r->qiov.size,
> + BLOCK_ACCT_WRITE);
> r->req.aiocb = sdc->dma_writev(r->sector << BDRV_SECTOR_BITS,
> &r->qiov,
> scsi_write_complete, r, r);
> }
> @@ -1710,7 +1714,7 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq
> *r, uint8_t *inbuf)
> if (!blk_enable_write_cache(s->qdev.conf.blk)) {
> /* The request is used as the AIO opaque value, so add a ref. */
> scsi_req_ref(&r->req);
> - 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, -1, 0,
> BLOCK_ACCT_FLUSH);
> r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_aio_complete, r);
> return;
> @@ -1777,6 +1781,7 @@ static void scsi_unmap_complete_noio(UnmapCBData *data,
> int ret)
> }
>
> block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
> + r->sector * BDRV_SECTOR_SIZE,
> r->sector_count * BDRV_SECTOR_SIZE,
> BLOCK_ACCT_UNMAP);
>
> @@ -1894,7 +1899,8 @@ static void scsi_write_same_complete(void *opaque, int
> ret)
> data->iov.iov_len);
> if (data->iov.iov_len) {
> block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
> - data->iov.iov_len, BLOCK_ACCT_WRITE);
> + data->sector << BDRV_SECTOR_BITS, data->iov.iov_len,
> + BLOCK_ACCT_WRITE);
> /* Reinitialize qiov, to handle unaligned WRITE SAME request
> * where final qiov may need smaller size */
> qemu_iovec_init_external(&data->qiov, &data->iov, 1);
> @@ -1943,6 +1949,7 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq
> *r, uint8_t *inbuf)
> /* The request is used as the AIO opaque value, so add a ref. */
> scsi_req_ref(&r->req);
> block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
> + r->req.cmd.lba * s->qdev.blocksize,
> nb_sectors * s->qdev.blocksize,
> BLOCK_ACCT_WRITE);
> r->req.aiocb = blk_aio_pwrite_zeroes(s->qdev.conf.blk,
> @@ -1969,7 +1976,8 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq
> *r, uint8_t *inbuf)
>
> scsi_req_ref(&r->req);
> block_acct_start(blk_get_stats(s->qdev.conf.blk), &r->acct,
> - data->iov.iov_len, BLOCK_ACCT_WRITE);
> + data->sector << BDRV_SECTOR_BITS, data->iov.iov_len,
> + BLOCK_ACCT_WRITE);
> r->req.aiocb = blk_aio_pwritev(s->qdev.conf.blk,
> data->sector << BDRV_SECTOR_BITS,
> &data->qiov, 0,
> @@ -2237,7 +2245,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest
> *req, uint8_t *buf)
> case SYNCHRONIZE_CACHE:
> /* The request is used as the AIO opaque value, so add a ref. */
> scsi_req_ref(&r->req);
> - 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, -1, 0,
> BLOCK_ACCT_FLUSH);
> r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_aio_complete, r);
> return 0;
> diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
> index de4c1966fea..655dfae9057 100644
> --- a/qemu-io-cmds.c
> +++ b/qemu-io-cmds.c
> @@ -1538,8 +1538,8 @@ static int aio_read_f(BlockBackend *blk, int argc, char
> **argv)
> }
>
> clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
> - block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
> - BLOCK_ACCT_READ);
> + block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->offset,
> + ctx->qiov.size, BLOCK_ACCT_READ);
> blk_aio_preadv(blk, ctx->offset, &ctx->qiov, ctx->flags, aio_read_done,
> ctx);
> return 0;
> @@ -1693,8 +1693,8 @@ static int aio_write_f(BlockBackend *blk, int argc,
> char **argv)
> }
>
> clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
> - block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
> - BLOCK_ACCT_WRITE);
> + block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->offset,
> + ctx->qiov.size, BLOCK_ACCT_WRITE);
>
> blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, ctx->flags,
> aio_write_done, ctx);
> @@ -1706,7 +1706,7 @@ static int aio_write_f(BlockBackend *blk, int argc,
> char **argv)
> static int aio_flush_f(BlockBackend *blk, int argc, char **argv)
> {
> BlockAcctCookie cookie;
> - block_acct_start(blk_get_stats(blk), &cookie, 0, BLOCK_ACCT_FLUSH);
> + block_acct_start(blk_get_stats(blk), &cookie, -1, 0, BLOCK_ACCT_FLUSH);
> blk_drain_all();
> block_acct_done(blk_get_stats(blk), &cookie);
> return 0;
> @@ -2325,8 +2325,8 @@ static int aio_discard_f(BlockBackend *blk, int argc,
> char **argv)
>
> clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
> ctx->qiov.size = count;
> - block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
> - BLOCK_ACCT_UNMAP);
> + block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->offset,
> + ctx->qiov.size, BLOCK_ACCT_UNMAP);
> blk_aio_pdiscard(blk, ctx->offset, count, aio_discard_done, ctx);
>
> return 0;
> diff --git a/system/dma-helpers.c b/system/dma-helpers.c
> index 0d592f64680..7bf41119ebc 100644
> --- a/system/dma-helpers.c
> +++ b/system/dma-helpers.c
> @@ -315,9 +315,9 @@ MemTxResult dma_buf_write(void *ptr, dma_addr_t len,
> dma_addr_t *residual,
> }
>
> void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
> - QEMUSGList *sg, enum BlockAcctType type)
> + QEMUSGList *sg, int64_t offset, enum BlockAcctType type)
> {
> - block_acct_start(blk_get_stats(blk), cookie, sg->size, type);
> + block_acct_start(blk_get_stats(blk), cookie, offset, sg->size, type);
> }
>
> uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end, int
> max_addr_bits)
> diff --git a/tests/unit/test-block-accounting.c
> b/tests/unit/test-block-accounting.c
> index 7aae491cfc2..0081502891c 100644
> --- a/tests/unit/test-block-accounting.c
> +++ b/tests/unit/test-block-accounting.c
> @@ -63,7 +63,7 @@ static void *reader_thread(void *opaque)
> while (!qatomic_read(&stop_workers)) {
> BlockAcctCookie cookie;
>
> - block_acct_start(stats, &cookie, 4096, BLOCK_ACCT_READ);
> + block_acct_start(stats, &cookie, -1, 4096, BLOCK_ACCT_READ);
> block_acct_done(stats, &cookie);
> }
>
> --
> 2.55.0
>
>
>
For the parts touching hw/nvme/*
Acked-by: Jesper Wendel Devantier <[email protected]>