Re: [Qemu-block] [PATCH v7 5/6] block: add throttle block filter driver

2017-08-24 Thread Stefan Hajnoczi
On Tue, Aug 22, 2017 at 01:15:34PM +0300, Manos Pitsidianakis wrote:
> @@ -3095,6 +3096,20 @@
>  '*tls-creds': 'str' } }
>  
>  ##
> +# @BlockdevOptionsThrottle:
> +#
> +# Driver specific block device options for the throttle driver
> +#
> +# @throttle-group:   the name of the throttle-group object to use. It
> +#must already exist.
> +# @file: reference to or definition of the data source block 
> device
> +# Since: 2.11
> +##
> +{ 'struct': 'BlockdevOptionsThrottle',
> +  'data': { '*throttle-group': 'str',

This field is optional but:

  group_name = qemu_opt_get(opts, QEMU_OPT_THROTTLE_GROUP_NAME);
  if (!group_name) {
  error_setg(errp, "Please specify a throttle group.");
  ret = EINVAL;
  goto fin;

Should it be mandatory?

> +'file' : 'BlockdevRef'
> + } }
> +##
>  # @BlockdevOptions:
>  #
>  # Options for creating a block device.  Many options are available for all
> @@ -3155,6 +3170,7 @@
>'replication':'BlockdevOptionsReplication',
>'sheepdog':   'BlockdevOptionsSheepdog',
>'ssh':'BlockdevOptionsSsh',
> +  'throttle':   'BlockdevOptionsThrottle',
>'vdi':'BlockdevOptionsGenericFormat',
>'vhdx':   'BlockdevOptionsGenericFormat',
>'vmdk':   'BlockdevOptionsGenericCOWFormat',
> diff --git a/include/block/throttle-groups.h b/include/block/throttle-groups.h
> index 82f030523f..ec969e84fe 100644
> --- a/include/block/throttle-groups.h
> +++ b/include/block/throttle-groups.h
> @@ -76,5 +76,6 @@ void coroutine_fn 
> throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm
>  void throttle_group_attach_aio_context(ThrottleGroupMember *tgm,
> AioContext *new_context);
>  void throttle_group_detach_aio_context(ThrottleGroupMember *tgm);
> +bool throttle_group_exists(const char *name);
>  
>  #endif
> diff --git a/include/qemu/throttle-options.h b/include/qemu/throttle-options.h
> index 182b7896e1..3528a8f4a2 100644
> --- a/include/qemu/throttle-options.h
> +++ b/include/qemu/throttle-options.h
> @@ -29,6 +29,7 @@
>  #define QEMU_OPT_BPS_WRITE_MAX "bps-write-max"
>  #define QEMU_OPT_BPS_WRITE_MAX_LENGTH "bps-write-max-length"
>  #define QEMU_OPT_IOPS_SIZE "iops-size"
> +#define QEMU_OPT_THROTTLE_GROUP_NAME "throttle-group"
>  
>  #define THROTTLE_OPT_PREFIX "throttling."
>  #define THROTTLE_OPTS \
> diff --git a/block/throttle-groups.c b/block/throttle-groups.c
> index a4268a954e..4b483a16d4 100644
> --- a/block/throttle-groups.c
> +++ b/block/throttle-groups.c
> @@ -101,7 +101,7 @@ static ThrottleGroup *throttle_group_by_name(const char 
> *name)
>  return NULL;
>  }
>  

/* Must be called with the global mutex held */
> -static bool throttle_group_exists(const char *name)
> +bool throttle_group_exists(const char *name)
>  {
>  return throttle_group_by_name(name) ? true : false;
>  }



Re: [Qemu-block] [PATCH v7 5/6] block: add throttle block filter driver

2017-08-22 Thread Manos Pitsidianakis

On Tue, Aug 22, 2017 at 04:16:26PM +0200, Alberto Garcia wrote:

On Tue 22 Aug 2017 12:15:34 PM CEST, Manos Pitsidianakis wrote:

@@ -548,6 +548,11 @@ void throttle_group_unregister_tgm(ThrottleGroupMember 
*tgm)
 ThrottleGroupMember *token;
 int i;

+if (!ts) {
+/* Discard uninitialized tgm */
+return;
+}
+


Is this change needed in case throttle_configure_tgm() fails?


Yes, now all errors are before throttle_group_register_tgm(), therefore 
the unregister part in throttle_close() will not have valid data.


signature.asc
Description: PGP signature


Re: [Qemu-block] [PATCH v7 5/6] block: add throttle block filter driver

2017-08-22 Thread Alberto Garcia
On Tue 22 Aug 2017 12:15:34 PM CEST, Manos Pitsidianakis wrote:
>  ##
> +# @BlockdevOptionsThrottle:
> +#
> +# Driver specific block device options for the throttle driver
> +#
> +# @throttle-group:   the name of the throttle-group object to use. It
> +#must already exist.
> +# @file: reference to or definition of the data source block 
> device
> +# Since: 2.11
> +##
> +{ 'struct': 'BlockdevOptionsThrottle',
> +  'data': { '*throttle-group': 'str',
> +'file' : 'BlockdevRef'
> + } }
> +##

I guess throttle-group is not optional here anymore ?

> @@ -548,6 +548,11 @@ void throttle_group_unregister_tgm(ThrottleGroupMember 
> *tgm)
>  ThrottleGroupMember *token;
>  int i;
>  
> +if (!ts) {
> +/* Discard uninitialized tgm */
> +return;
> +}
> +

Is this change needed in case throttle_configure_tgm() fails?

> +static int throttle_configure_tgm(BlockDriverState *bs,
> +  ThrottleGroupMember *tgm,
> +  QDict *options, Error **errp)
> +{
> +int ret;
> +const char *group_name;
> +Error *local_err = NULL;
> +QemuOpts *opts = qemu_opts_create(_opts, NULL, 0, _abort);
> +
> +qemu_opts_absorb_qdict(opts, options, _err);
> +if (local_err) {
> +error_propagate(errp, local_err);
> +ret = -EINVAL;
> +goto fin;
> +}
> +
> +group_name = qemu_opt_get(opts, QEMU_OPT_THROTTLE_GROUP_NAME);
> +if (!group_name) {
> +error_setg(errp, "Please specify a throttle group.");
> +ret = EINVAL;
> +goto fin;
> +} else if (!throttle_group_exists(group_name)) {
> +error_setg(errp, "Throttle group '%s' does not exist.", group_name);
> +ret = EINVAL;
> +goto fin;
> +}

It should be -EINVAL (negative value) in both cases.

Berto



[Qemu-block] [PATCH v7 5/6] block: add throttle block filter driver

2017-08-22 Thread Manos Pitsidianakis
block/throttle.c uses existing I/O throttle infrastructure inside a
block filter driver. I/O operations are intercepted in the filter's
read/write coroutines, and referred to block/throttle-groups.c

The driver can be used with the syntax
-drive driver=throttle,file.filename=foo.qcow2,throttle-group=bar

which registers the throttle filter node with the ThrottleGroup 'bar'. The
given group must be created beforehand with object-add or -object.

Signed-off-by: Manos Pitsidianakis 
---
 qapi/block-core.json|  18 ++-
 include/block/throttle-groups.h |   1 +
 include/qemu/throttle-options.h |   1 +
 block/throttle-groups.c |   7 +-
 block/throttle.c| 250 
 block/Makefile.objs |   1 +
 6 files changed, 276 insertions(+), 2 deletions(-)
 create mode 100644 block/throttle.c

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 0bdc69aa5f..405c181954 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -,6 +,7 @@
 # Drivers that are supported in block device operations.
 #
 # @vxhs: Since 2.10
+# @throttle: Since 2.11
 #
 # Since: 2.9
 ##
@@ -2231,7 +2232,7 @@
 'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
 'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed',
 'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
-'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
+'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
 
 ##
 # @BlockdevOptionsFile:
@@ -3095,6 +3096,20 @@
 '*tls-creds': 'str' } }
 
 ##
+# @BlockdevOptionsThrottle:
+#
+# Driver specific block device options for the throttle driver
+#
+# @throttle-group:   the name of the throttle-group object to use. It
+#must already exist.
+# @file: reference to or definition of the data source block device
+# Since: 2.11
+##
+{ 'struct': 'BlockdevOptionsThrottle',
+  'data': { '*throttle-group': 'str',
+'file' : 'BlockdevRef'
+ } }
+##
 # @BlockdevOptions:
 #
 # Options for creating a block device.  Many options are available for all
@@ -3155,6 +3170,7 @@
   'replication':'BlockdevOptionsReplication',
   'sheepdog':   'BlockdevOptionsSheepdog',
   'ssh':'BlockdevOptionsSsh',
+  'throttle':   'BlockdevOptionsThrottle',
   'vdi':'BlockdevOptionsGenericFormat',
   'vhdx':   'BlockdevOptionsGenericFormat',
   'vmdk':   'BlockdevOptionsGenericCOWFormat',
diff --git a/include/block/throttle-groups.h b/include/block/throttle-groups.h
index 82f030523f..ec969e84fe 100644
--- a/include/block/throttle-groups.h
+++ b/include/block/throttle-groups.h
@@ -76,5 +76,6 @@ void coroutine_fn 
throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm
 void throttle_group_attach_aio_context(ThrottleGroupMember *tgm,
AioContext *new_context);
 void throttle_group_detach_aio_context(ThrottleGroupMember *tgm);
+bool throttle_group_exists(const char *name);
 
 #endif
diff --git a/include/qemu/throttle-options.h b/include/qemu/throttle-options.h
index 182b7896e1..3528a8f4a2 100644
--- a/include/qemu/throttle-options.h
+++ b/include/qemu/throttle-options.h
@@ -29,6 +29,7 @@
 #define QEMU_OPT_BPS_WRITE_MAX "bps-write-max"
 #define QEMU_OPT_BPS_WRITE_MAX_LENGTH "bps-write-max-length"
 #define QEMU_OPT_IOPS_SIZE "iops-size"
+#define QEMU_OPT_THROTTLE_GROUP_NAME "throttle-group"
 
 #define THROTTLE_OPT_PREFIX "throttling."
 #define THROTTLE_OPTS \
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
index a4268a954e..4b483a16d4 100644
--- a/block/throttle-groups.c
+++ b/block/throttle-groups.c
@@ -101,7 +101,7 @@ static ThrottleGroup *throttle_group_by_name(const char 
*name)
 return NULL;
 }
 
-static bool throttle_group_exists(const char *name)
+bool throttle_group_exists(const char *name)
 {
 return throttle_group_by_name(name) ? true : false;
 }
@@ -548,6 +548,11 @@ void throttle_group_unregister_tgm(ThrottleGroupMember 
*tgm)
 ThrottleGroupMember *token;
 int i;
 
+if (!ts) {
+/* Discard uninitialized tgm */
+return;
+}
+
 assert(tgm->pending_reqs[0] == 0 && tgm->pending_reqs[1] == 0);
 assert(qemu_co_queue_empty(>throttled_reqs[0]));
 assert(qemu_co_queue_empty(>throttled_reqs[1]));
diff --git a/block/throttle.c b/block/throttle.c
new file mode 100644
index 00..910de27dcd
--- /dev/null
+++ b/block/throttle.c
@@ -0,0 +1,250 @@
+/*
+ * QEMU block throttling filter driver infrastructure
+ *
+ * Copyright (c) 2017 Manos Pitsidianakis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that