aboutsummaryrefslogtreecommitdiff
path: root/block/nvme.c
diff options
context:
space:
mode:
authorPhilippe Mathieu-Daudé <philmd@redhat.com>2020-10-01 18:29:39 +0200
committerStefan Hajnoczi <stefanha@redhat.com>2020-10-23 13:42:16 +0100
commitf25e7ab2b091fae1ae3e9f55b5244ddcdb1653bb (patch)
treeb78df72add39004c843c1fcd67157ff0fcc04a1f /block/nvme.c
parent4c5b97bfd0dd54dc27717ae8d1cd10e14eef1430 (diff)
downloadqemu-f25e7ab2b091fae1ae3e9f55b5244ddcdb1653bb.zip
qemu-f25e7ab2b091fae1ae3e9f55b5244ddcdb1653bb.tar.gz
qemu-f25e7ab2b091fae1ae3e9f55b5244ddcdb1653bb.tar.bz2
block/nvme: Add driver statistics for access alignment and hw errors
Keep statistics of some hardware errors, and number of aligned/unaligned I/O accesses. QMP example booting a full RHEL 8.3 aarch64 guest: { "execute": "query-blockstats" } { "return": [ { "device": "", "node-name": "drive0", "stats": { "flush_total_time_ns": 6026948, "wr_highest_offset": 3383991230464, "wr_total_time_ns": 807450995, "failed_wr_operations": 0, "failed_rd_operations": 0, "wr_merged": 3, "wr_bytes": 50133504, "failed_unmap_operations": 0, "failed_flush_operations": 0, "account_invalid": false, "rd_total_time_ns": 1846979900, "flush_operations": 130, "wr_operations": 659, "rd_merged": 1192, "rd_bytes": 218244096, "account_failed": false, "idle_time_ns": 2678641497, "rd_operations": 7406, }, "driver-specific": { "driver": "nvme", "completion-errors": 0, "unaligned-accesses": 2959, "aligned-accesses": 4477 }, "qdev": "/machine/peripheral-anon/device[0]/virtio-backend" } ] } Suggested-by: Stefan Hajnoczi <stefanha@gmail.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> Acked-by: Markus Armbruster <armbru@redhat.com> Message-id: 20201001162939.1567915-1-philmd@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/nvme.c')
-rw-r--r--block/nvme.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/block/nvme.c b/block/nvme.c
index b48f6f2..739a0a7 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -128,6 +128,12 @@ struct BDRVNVMeState {
/* PCI address (required for nvme_refresh_filename()) */
char *device;
+
+ struct {
+ uint64_t completion_errors;
+ uint64_t aligned_accesses;
+ uint64_t unaligned_accesses;
+ } stats;
};
#define NVME_BLOCK_OPT_DEVICE "device"
@@ -384,6 +390,9 @@ static bool nvme_process_completion(NVMeQueuePair *q)
break;
}
ret = nvme_translate_error(c);
+ if (ret) {
+ s->stats.completion_errors++;
+ }
q->cq.head = (q->cq.head + 1) % NVME_QUEUE_SIZE;
if (!q->cq.head) {
q->cq_phase = !q->cq_phase;
@@ -1155,8 +1164,10 @@ static int nvme_co_prw(BlockDriverState *bs, uint64_t offset, uint64_t bytes,
assert(QEMU_IS_ALIGNED(bytes, s->page_size));
assert(bytes <= s->max_transfer);
if (nvme_qiov_aligned(bs, qiov)) {
+ s->stats.aligned_accesses++;
return nvme_co_prw_aligned(bs, offset, bytes, qiov, is_write, flags);
}
+ s->stats.unaligned_accesses++;
trace_nvme_prw_buffered(s, offset, bytes, qiov->niov, is_write);
buf = qemu_try_memalign(s->page_size, bytes);
@@ -1452,6 +1463,21 @@ static void nvme_unregister_buf(BlockDriverState *bs, void *host)
qemu_vfio_dma_unmap(s->vfio, host);
}
+static BlockStatsSpecific *nvme_get_specific_stats(BlockDriverState *bs)
+{
+ BlockStatsSpecific *stats = g_new(BlockStatsSpecific, 1);
+ BDRVNVMeState *s = bs->opaque;
+
+ stats->driver = BLOCKDEV_DRIVER_NVME;
+ stats->u.nvme = (BlockStatsSpecificNvme) {
+ .completion_errors = s->stats.completion_errors,
+ .aligned_accesses = s->stats.aligned_accesses,
+ .unaligned_accesses = s->stats.unaligned_accesses,
+ };
+
+ return stats;
+}
+
static const char *const nvme_strong_runtime_opts[] = {
NVME_BLOCK_OPT_DEVICE,
NVME_BLOCK_OPT_NAMESPACE,
@@ -1485,6 +1511,7 @@ static BlockDriver bdrv_nvme = {
.bdrv_refresh_filename = nvme_refresh_filename,
.bdrv_refresh_limits = nvme_refresh_limits,
.strong_runtime_opts = nvme_strong_runtime_opts,
+ .bdrv_get_specific_stats = nvme_get_specific_stats,
.bdrv_detach_aio_context = nvme_detach_aio_context,
.bdrv_attach_aio_context = nvme_attach_aio_context,