diff mbox

[PULL,33/44] block: New option to define the intervals for collecting I/O statistics

Message ID 1447164879-6756-34-git-send-email-stefanha@redhat.com
State New
Headers show

Commit Message

Stefan Hajnoczi Nov. 10, 2015, 2:14 p.m. UTC
From: Alberto Garcia <berto@igalia.com>

The BlockAcctStats structure contains a list of BlockAcctTimedStats.
Each one of these collects statistics about the minimum, maximum and
average latencies of all I/O operations in a certain interval of time.

This patch adds a new "stats-intervals" option that allows defining
these intervals.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Message-id: 41cbcd334a61c6157f0f495cdfd21eff6c156f2a.1446044837.git.berto@igalia.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 blockdev.c           | 37 +++++++++++++++++++++++++++++++++++++
 qapi/block-core.json |  4 ++++
 2 files changed, 41 insertions(+)

Comments

Eric Blake Nov. 10, 2015, 5:23 p.m. UTC | #1
On 11/10/2015 07:14 AM, Stefan Hajnoczi wrote:
> From: Alberto Garcia <berto@igalia.com>
> 
> The BlockAcctStats structure contains a list of BlockAcctTimedStats.
> Each one of these collects statistics about the minimum, maximum and
> average latencies of all I/O operations in a certain interval of time.
> 
> This patch adds a new "stats-intervals" option that allows defining
> these intervals.
> 
> Signed-off-by: Alberto Garcia <berto@igalia.com>
> Message-id: 41cbcd334a61c6157f0f495cdfd21eff6c156f2a.1446044837.git.berto@igalia.com
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  blockdev.c           | 37 +++++++++++++++++++++++++++++++++++++
>  qapi/block-core.json |  4 ++++
>  2 files changed, 41 insertions(+)

> +++ b/qapi/block-core.json
> @@ -1503,6 +1503,9 @@
>  # @stats-account-failed: #optional whether to include failed
>  #                         operations when computing latency and last
>  #                         access statistics (default: true) (Since 2.5)
> +# @stats-intervals: #optional colon-separated list of intervals for
> +#                   collecting I/O statistics, in seconds (default: none)
> +#                   (Since 2.5)

Eww. Sorry for not noticing this sooner, but can we please fix this to be:

'*stats-intervals':['int']

Having to post-process parse for colons means that the JSON interface
was not properly defined.

I'm okay if the fix is a followup, but we need to get it in before 2.5
bakes in the gross interface.

>  # @detect-zeroes: #optional detect and optimize zero writes (Since 2.1)
>  #                 (default: off)
>  #
> @@ -1520,6 +1523,7 @@
>              '*read-only': 'bool',
>              '*stats-account-invalid': 'bool',
>              '*stats-account-failed': 'bool',
> +            '*stats-intervals': 'str',
>              '*detect-zeroes': 'BlockdevDetectZeroesOptions' } }
>  
>  ##
>
Markus Armbruster Nov. 10, 2015, 6:49 p.m. UTC | #2
Eric Blake <eblake@redhat.com> writes:

> On 11/10/2015 07:14 AM, Stefan Hajnoczi wrote:
>> From: Alberto Garcia <berto@igalia.com>
>> 
>> The BlockAcctStats structure contains a list of BlockAcctTimedStats.
>> Each one of these collects statistics about the minimum, maximum and
>> average latencies of all I/O operations in a certain interval of time.
>> 
>> This patch adds a new "stats-intervals" option that allows defining
>> these intervals.
>> 
>> Signed-off-by: Alberto Garcia <berto@igalia.com>
>> Message-id: 41cbcd334a61c6157f0f495cdfd21eff6c156f2a.1446044837.git.berto@igalia.com
>> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
>> ---
>>  blockdev.c           | 37 +++++++++++++++++++++++++++++++++++++
>>  qapi/block-core.json |  4 ++++
>>  2 files changed, 41 insertions(+)
>
>> +++ b/qapi/block-core.json
>> @@ -1503,6 +1503,9 @@
>>  # @stats-account-failed: #optional whether to include failed
>>  #                         operations when computing latency and last
>>  #                         access statistics (default: true) (Since 2.5)
>> +# @stats-intervals: #optional colon-separated list of intervals for
>> +#                   collecting I/O statistics, in seconds (default: none)
>> +#                   (Since 2.5)
>
> Eww. Sorry for not noticing this sooner, but can we please fix this to be:
>
> '*stats-intervals':['int']
>
> Having to post-process parse for colons means that the JSON interface
> was not properly defined.

Basic QMP rule: never encode in strings when a natural JSON encoding
exists.

If you want a fancy string encoding for HMP or command line, use
suitable visitors.  If I remember correctly, NumaNodeOptions member cpus
can serve as example for a list of integers.  Suggest to start at
parse_numa().

> I'm okay if the fix is a followup, but we need to get it in before 2.5
> bakes in the gross interface.

For 2.5, either fix it, revert it, or rename it to x-.  It must not
become ABI in this state.

>>  # @detect-zeroes: #optional detect and optimize zero writes (Since 2.1)
>>  #                 (default: off)
>>  #
>> @@ -1520,6 +1523,7 @@
>>              '*read-only': 'bool',
>>              '*stats-account-invalid': 'bool',
>>              '*stats-account-failed': 'bool',
>> +            '*stats-intervals': 'str',
>>              '*detect-zeroes': 'BlockdevDetectZeroesOptions' } }
>>  
>>  ##
>>
Alberto Garcia Nov. 11, 2015, 11:10 a.m. UTC | #3
On Tue 10 Nov 2015 06:23:36 PM CET, Eric Blake <eblake@redhat.com> wrote:

>> +# @stats-intervals: #optional colon-separated list of intervals for
>> +#                   collecting I/O statistics, in seconds (default: none)
>> +#                   (Since 2.5)
>
> Eww. Sorry for not noticing this sooner, but can we please fix this to
>be:
>
> '*stats-intervals':['int']

No problem, I'll send a follow-up patch asap.

I was actually expecting that there would be some debate about this; in
the series description I mentioned that I considered an alternate API,
although rather than ['int'] it was ['BlockdevStatsInterval'], with
BlockdevStatsInterval being a struct with a sole member 'length': 'int'.

      stats-intervals.0.length=60,
      stats-intervals.1.length=3600,
      stats-intervals.2.length=86400

It's more future proof than just having a list of integers, but I
honestly don't know if there's any use case for additional parameters of
the intervals.

https://lists.gnu.org/archive/html/qemu-block/2015-10/msg01068.html

Berto
diff mbox

Patch

diff --git a/blockdev.c b/blockdev.c
index 5b7aac3..769859c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -442,6 +442,7 @@  static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
     int bdrv_flags = 0;
     int on_read_error, on_write_error;
     bool account_invalid, account_failed;
+    const char *stats_intervals;
     BlockBackend *blk;
     BlockDriverState *bs;
     ThrottleConfig cfg;
@@ -481,6 +482,8 @@  static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
     account_invalid = qemu_opt_get_bool(opts, "stats-account-invalid", true);
     account_failed = qemu_opt_get_bool(opts, "stats-account-failed", true);
 
+    stats_intervals = qemu_opt_get(opts, "stats-intervals");
+
     extract_common_blockdev_options(opts, &bdrv_flags, &throttling_group, &cfg,
                                     &detect_zeroes, &error);
     if (error) {
@@ -579,6 +582,35 @@  static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
         }
 
         block_acct_init(blk_get_stats(blk), account_invalid, account_failed);
+
+        if (stats_intervals) {
+            char **intervals = g_strsplit(stats_intervals, ":", 0);
+            unsigned i;
+
+            if (*stats_intervals == '\0') {
+                error_setg(&error, "stats-intervals can't have an empty value");
+            }
+
+            for (i = 0; !error && intervals[i] != NULL; i++) {
+                unsigned long long val;
+                if (parse_uint_full(intervals[i], &val, 10) == 0 &&
+                    val > 0 && val <= UINT_MAX) {
+                    block_acct_add_interval(blk_get_stats(blk), val);
+                } else {
+                    error_setg(&error, "Invalid interval length: '%s'",
+                               intervals[i]);
+                }
+            }
+
+            g_strfreev(intervals);
+
+            if (error) {
+                error_propagate(errp, error);
+                blk_unref(blk);
+                blk = NULL;
+                goto err_no_bs_opts;
+            }
+        }
     }
 
     blk_set_on_error(blk, on_read_error, on_write_error);
@@ -3655,6 +3687,11 @@  QemuOptsList qemu_common_drive_opts = {
             .type = QEMU_OPT_BOOL,
             .help = "whether to account for failed I/O operations "
                     "in the statistics",
+        },{
+            .name = "stats-intervals",
+            .type = QEMU_OPT_STRING,
+            .help = "colon-separated list of intervals "
+                    "for collecting I/O statistics, in seconds",
         },
         { /* end of list */ }
     },
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 0742794..273d073 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1503,6 +1503,9 @@ 
 # @stats-account-failed: #optional whether to include failed
 #                         operations when computing latency and last
 #                         access statistics (default: true) (Since 2.5)
+# @stats-intervals: #optional colon-separated list of intervals for
+#                   collecting I/O statistics, in seconds (default: none)
+#                   (Since 2.5)
 # @detect-zeroes: #optional detect and optimize zero writes (Since 2.1)
 #                 (default: off)
 #
@@ -1520,6 +1523,7 @@ 
             '*read-only': 'bool',
             '*stats-account-invalid': 'bool',
             '*stats-account-failed': 'bool',
+            '*stats-intervals': 'str',
             '*detect-zeroes': 'BlockdevDetectZeroesOptions' } }
 
 ##