aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberto Garcia <berto@igalia.com>2015-10-28 17:33:03 +0200
committerKevin Wolf <kwolf@redhat.com>2015-11-12 16:22:45 +0100
commit7ee12dafe96a86dfa96af38cea1289305e429a55 (patch)
tree28c88720535e3822419bec2db0ca32be053c3118
parentcb38fffbc968e797ae32039b1e2c47b940b30cb4 (diff)
block: Add statistics for failed and invalid I/O operations
This patch adds the block_acct_failed() and block_acct_invalid() functions to allow keeping track of failed and invalid I/O operations. The number of failed and invalid operations is exposed in BlockDeviceStats. We don't keep track of the time spent on invalid operations because they are cancelled immediately when they are started. Signed-off-by: Alberto Garcia <berto@igalia.com> Message-id: a7256ccb883a86356b1c6c46b5a29ed5448546a5.1446044837.git.berto@igalia.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
-rw-r--r--block/accounting.c23
-rw-r--r--block/qapi.c10
-rw-r--r--include/block/accounting.h4
-rw-r--r--qapi/block-core.json23
-rw-r--r--qmp-commands.hx12
5 files changed, 71 insertions, 1 deletions
diff --git a/block/accounting.c b/block/accounting.c
index d427fa8fb8..49a9444377 100644
--- a/block/accounting.c
+++ b/block/accounting.c
@@ -51,6 +51,29 @@ void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie)
stats->last_access_time_ns = time_ns;
}
+void block_acct_failed(BlockAcctStats *stats, BlockAcctCookie *cookie)
+{
+ int64_t time_ns = qemu_clock_get_ns(clock_type);
+
+ assert(cookie->type < BLOCK_MAX_IOTYPE);
+
+ stats->failed_ops[cookie->type]++;
+ stats->total_time_ns[cookie->type] += time_ns - cookie->start_time_ns;
+ stats->last_access_time_ns = time_ns;
+}
+
+void block_acct_invalid(BlockAcctStats *stats, enum BlockAcctType type)
+{
+ assert(type < BLOCK_MAX_IOTYPE);
+
+ /* block_acct_done() and block_acct_failed() update
+ * total_time_ns[], but this one does not. The reason is that
+ * invalid requests are accounted during their submission,
+ * therefore there's no actual I/O involved. */
+
+ stats->invalid_ops[type]++;
+ stats->last_access_time_ns = qemu_clock_get_ns(clock_type);
+}
void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type,
int num_requests)
diff --git a/block/qapi.c b/block/qapi.c
index 9799656761..d1a6bdc1d2 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -351,6 +351,16 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs,
s->stats->wr_bytes = stats->nr_bytes[BLOCK_ACCT_WRITE];
s->stats->rd_operations = stats->nr_ops[BLOCK_ACCT_READ];
s->stats->wr_operations = stats->nr_ops[BLOCK_ACCT_WRITE];
+
+ s->stats->failed_rd_operations = stats->failed_ops[BLOCK_ACCT_READ];
+ s->stats->failed_wr_operations = stats->failed_ops[BLOCK_ACCT_WRITE];
+ s->stats->failed_flush_operations = stats->failed_ops[BLOCK_ACCT_FLUSH];
+
+ s->stats->invalid_rd_operations = stats->invalid_ops[BLOCK_ACCT_READ];
+ s->stats->invalid_wr_operations = stats->invalid_ops[BLOCK_ACCT_WRITE];
+ s->stats->invalid_flush_operations =
+ stats->invalid_ops[BLOCK_ACCT_FLUSH];
+
s->stats->rd_merged = stats->merged[BLOCK_ACCT_READ];
s->stats->wr_merged = stats->merged[BLOCK_ACCT_WRITE];
s->stats->flush_operations = stats->nr_ops[BLOCK_ACCT_FLUSH];
diff --git a/include/block/accounting.h b/include/block/accounting.h
index 4b2b999bd0..b50e3cc8d2 100644
--- a/include/block/accounting.h
+++ b/include/block/accounting.h
@@ -38,6 +38,8 @@ enum BlockAcctType {
typedef struct BlockAcctStats {
uint64_t nr_bytes[BLOCK_MAX_IOTYPE];
uint64_t nr_ops[BLOCK_MAX_IOTYPE];
+ uint64_t invalid_ops[BLOCK_MAX_IOTYPE];
+ uint64_t failed_ops[BLOCK_MAX_IOTYPE];
uint64_t total_time_ns[BLOCK_MAX_IOTYPE];
uint64_t merged[BLOCK_MAX_IOTYPE];
int64_t last_access_time_ns;
@@ -52,6 +54,8 @@ typedef struct BlockAcctCookie {
void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie,
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);
void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type,
int num_requests);
int64_t block_acct_idle_time_ns(BlockAcctStats *stats);
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 597281821b..009b7c88f9 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -452,6 +452,24 @@
# nanoseconds. If the field is absent it means that
# there haven't been any operations yet (Since 2.5).
#
+# @failed_rd_operations: The number of failed read operations
+# performed by the device (Since 2.5)
+#
+# @failed_wr_operations: The number of failed write operations
+# performed by the device (Since 2.5)
+#
+# @failed_flush_operations: The number of failed flush operations
+# performed by the device (Since 2.5)
+#
+# @invalid_rd_operations: The number of invalid read operations
+# performed by the device (Since 2.5)
+#
+# @invalid_wr_operations: The number of invalid write operations
+# performed by the device (Since 2.5)
+#
+# @invalid_flush_operations: The number of invalid flush operations
+# performed by the device (Since 2.5)
+#
# Since: 0.14.0
##
{ 'struct': 'BlockDeviceStats',
@@ -459,7 +477,10 @@
'wr_operations': 'int', 'flush_operations': 'int',
'flush_total_time_ns': 'int', 'wr_total_time_ns': 'int',
'rd_total_time_ns': 'int', 'wr_highest_offset': 'int',
- 'rd_merged': 'int', 'wr_merged': 'int', '*idle_time_ns': 'int' } }
+ 'rd_merged': 'int', 'wr_merged': 'int', '*idle_time_ns': 'int',
+ 'failed_rd_operations': 'int', 'failed_wr_operations': 'int',
+ 'failed_flush_operations': 'int', 'invalid_rd_operations': 'int',
+ 'invalid_wr_operations': 'int', 'invalid_flush_operations': 'int' } }
##
# @BlockStats:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5c4c16fe9b..b031df6942 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2587,6 +2587,18 @@ Each json-object contain the following:
nanoseconds. If the field is absent it means
that there haven't been any operations yet
(json-int, optional)
+ - "failed_rd_operations": number of failed read operations
+ (json-int)
+ - "failed_wr_operations": number of failed write operations
+ (json-int)
+ - "failed_flush_operations": number of failed flush operations
+ (json-int)
+ - "invalid_rd_operations": number of invalid read operations
+ (json-int)
+ - "invalid_wr_operations": number of invalid write operations
+ (json-int)
+ - "invalid_flush_operations": number of invalid flush operations
+ (json-int)
- "parent": Contains recursively the statistics of the underlying
protocol (e.g. the host file for a qcow2 image). If there is
no underlying protocol, this field is omitted