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]>



Reply via email to