From patchwork Thu Oct 22 08:11:16 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alberto Garcia X-Patchwork-Id: 534269 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id C009D141317 for ; Thu, 22 Oct 2015 19:13:05 +1100 (AEDT) Received: from localhost ([::1]:57430 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZpAzf-0007Fa-Lf for incoming@patchwork.ozlabs.org; Thu, 22 Oct 2015 04:13:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34442) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZpAyx-000625-Pm for qemu-devel@nongnu.org; Thu, 22 Oct 2015 04:12:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZpAys-0007yW-Nl for qemu-devel@nongnu.org; Thu, 22 Oct 2015 04:12:19 -0400 Received: from smtp3.mundo-r.com ([212.51.32.191]:64686 helo=smtp4.mundo-r.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZpAys-0007y1-9c; Thu, 22 Oct 2015 04:12:14 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CwAgA+mShW/5tjdVteGQEBAg4BAQGDCIFDqS0BAQEBAQEFAYENAY8yhCEBDYFZhh0CgTo4FAEBAQEBAQGBCoQvAQEEJ1IQPxI8GxmINAHEXQEshjCJbWUHhC4FhzUHhkg/h2eNHoFYh2OKHohLHwEBQoFKRAMdgVhvhHoEgUUBAQE X-IPAS-Result: A2CwAgA+mShW/5tjdVteGQEBAg4BAQGDCIFDqS0BAQEBAQEFAYENAY8yhCEBDYFZhh0CgTo4FAEBAQEBAQGBCoQvAQEEJ1IQPxI8GxmINAHEXQEshjCJbWUHhC4FhzUHhkg/h2eNHoFYh2OKHohLHwEBQoFKRAMdgVhvhHoEgUUBAQE X-IronPort-AV: E=Sophos;i="5.20,181,1444687200"; d="scan'208";a="36785422" Received: from fanzine.igalia.com ([91.117.99.155]) by smtp4.mundo-r.com with ESMTP; 22 Oct 2015 10:12:10 +0200 Received: from dsl-hkibrasgw4-50df50-201.dhcp.inet.fi ([80.223.80.201] helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim) id 1ZpAyn-0001Ku-Rm; Thu, 22 Oct 2015 10:12:10 +0200 Received: from berto by perseus.local with local (Exim 4.86) (envelope-from ) id 1ZpAya-0007Qu-9r; Thu, 22 Oct 2015 11:11:56 +0300 From: Alberto Garcia To: qemu-devel@nongnu.org Date: Thu, 22 Oct 2015 11:11:16 +0300 Message-Id: X-Mailer: git-send-email 2.6.1 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 212.51.32.191 Cc: Kevin Wolf , Alberto Garcia , qemu-block@nongnu.org, Markus Armbruster , Max Reitz , Stefan Hajnoczi Subject: [Qemu-devel] [PATCH v3 06/21] block: Add statistics for failed and invalid I/O operations X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- block/accounting.c | 23 +++++++++++++++++++++++ block/qapi.c | 10 ++++++++++ include/block/accounting.h | 4 ++++ qapi/block-core.json | 23 ++++++++++++++++++++++- qmp-commands.hx | 12 ++++++++++++ 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/block/accounting.c b/block/accounting.c index d427fa8..49a9444 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 539c2e3..84d8412 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 4b2b999..b50e3cc 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 69c3e1f..1e9b9a6 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 f44b2ba..8c0f94e 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -2530,6 +2530,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