All of lore.kernel.org
 help / color / mirror / Atom feed
From: Manos Pitsidianakis <el13635@mail.ntua.gr>
To: qemu-devel <qemu-devel@nongnu.org>
Cc: Kevin Wolf <kwolf@redhat.com>,
	Stefan Hajnoczi <stefanha@redhat.com>,
	Alberto Garcia <berto@igalia.com>,
	qemu-block <qemu-block@nongnu.org>
Subject: [Qemu-devel] [PATCH v3 5/7] block: add throttle block filter driver
Date: Mon, 31 Jul 2017 12:54:41 +0300	[thread overview]
Message-ID: <20170731095443.28211-6-el13635@mail.ntua.gr> (raw)
In-Reply-To: <20170731095443.28211-1-el13635@mail.ntua.gr>

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, \
        limits.iops-total=...,throttle-group=bar

The configuration flags and their semantics are identical to the
hardcoded throttling ones.

A node can be created referring to an existing group, and will overwrite
its limits if any are specified, otherwise they are retained.

Signed-off-by: Manos Pitsidianakis <el13635@mail.ntua.gr>
---
 block/Makefile.objs             |   1 +
 block/throttle.c                | 395 ++++++++++++++++++++++++++++++++++++++++
 include/qemu/throttle-options.h |   1 +
 3 files changed, 397 insertions(+)
 create mode 100644 block/throttle.c

diff --git a/block/Makefile.objs b/block/Makefile.objs
index 2aaede4ae1..6eaf78a046 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -25,6 +25,7 @@ block-obj-y += accounting.o dirty-bitmap.o
 block-obj-y += write-threshold.o
 block-obj-y += backup.o
 block-obj-$(CONFIG_REPLICATION) += replication.o
+block-obj-y += throttle.o
 
 block-obj-y += crypto.o
 
diff --git a/block/throttle.c b/block/throttle.c
new file mode 100644
index 0000000000..f3395462fb
--- /dev/null
+++ b/block/throttle.c
@@ -0,0 +1,395 @@
+/*
+ * 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 it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "block/throttle-groups.h"
+#include "qemu/throttle-options.h"
+#include "qapi/error.h"
+
+#undef THROTTLE_OPT_PREFIX
+#define THROTTLE_OPT_PREFIX "limits."
+static QemuOptsList throttle_opts = {
+    .name = "throttle",
+    .head = QTAILQ_HEAD_INITIALIZER(throttle_opts.head),
+    .desc = {
+        THROTTLE_OPTS,
+        {
+            .name = QEMU_OPT_THROTTLE_GROUP_NAME,
+            .type = QEMU_OPT_STRING,
+            .help = "throttle group name",
+        },
+        { /* end of list */ }
+    },
+};
+
+/* Extract ThrottleConfig options. Assumes cfg is initialized and will be
+ * checked for validity.
+ */
+static int throttle_extract_options(QemuOpts *opts, ThrottleConfig *cfg,
+                                     Error **errp)
+{
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL)) {
+        cfg->buckets[THROTTLE_BPS_TOTAL].avg =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL,
+                                0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ)) {
+        cfg->buckets[THROTTLE_BPS_READ].avg  =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ,
+                                0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE)) {
+        cfg->buckets[THROTTLE_BPS_WRITE].avg =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE,
+                                0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL)) {
+        cfg->buckets[THROTTLE_OPS_TOTAL].avg =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL,
+                                0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ)) {
+        cfg->buckets[THROTTLE_OPS_READ].avg =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ,
+                                0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE)) {
+        cfg->buckets[THROTTLE_OPS_WRITE].avg =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE,
+                                0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL_MAX)) {
+        cfg->buckets[THROTTLE_BPS_TOTAL].max =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_BPS_TOTAL_MAX, 0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ_MAX)) {
+        cfg->buckets[THROTTLE_BPS_READ].max  =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_BPS_READ_MAX, 0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE_MAX)) {
+        cfg->buckets[THROTTLE_BPS_WRITE].max =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_BPS_WRITE_MAX, 0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL_MAX)) {
+        cfg->buckets[THROTTLE_OPS_TOTAL].max =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_IOPS_TOTAL_MAX, 0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ_MAX)) {
+        cfg->buckets[THROTTLE_OPS_READ].max =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_IOPS_READ_MAX, 0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE_MAX)) {
+        cfg->buckets[THROTTLE_OPS_WRITE].max =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_IOPS_WRITE_MAX, 0);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL_MAX_LENGTH)) {
+        if (qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_BPS_TOTAL_MAX_LENGTH, 1) > UINT_MAX) {
+            error_setg(errp, "%s value must be in the range [0, %u]",
+                       THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL_MAX_LENGTH,
+                       UINT_MAX);
+            return -1;
+        }
+        cfg->buckets[THROTTLE_BPS_TOTAL].burst_length =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_BPS_TOTAL_MAX_LENGTH, 1);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ_MAX_LENGTH)) {
+        if (qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_BPS_READ_MAX_LENGTH, 1) > UINT_MAX) {
+            error_setg(errp, "%s must be in the range [0, %u]",
+                       THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ_MAX_LENGTH,
+                       UINT_MAX);
+            return -1;
+        }
+        cfg->buckets[THROTTLE_BPS_READ].burst_length  =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_BPS_READ_MAX_LENGTH, 1);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE_MAX_LENGTH)) {
+        if (qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_BPS_WRITE_MAX_LENGTH, 1) > UINT_MAX) {
+            error_setg(errp, "%s must be in the range [0, %u]",
+                       THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE_MAX_LENGTH,
+                       UINT_MAX);
+            return -1;
+        }
+        cfg->buckets[THROTTLE_BPS_WRITE].burst_length =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_BPS_WRITE_MAX_LENGTH, 1);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL_MAX_LENGTH)) {
+        if (qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_IOPS_TOTAL_MAX_LENGTH, 1) > UINT_MAX) {
+            error_setg(errp, "%s must be in the range [0, %u]",
+                       THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL_MAX_LENGTH,
+                       UINT_MAX);
+            return -1;
+        }
+        cfg->buckets[THROTTLE_OPS_TOTAL].burst_length =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_IOPS_TOTAL_MAX_LENGTH, 1);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ_MAX_LENGTH)) {
+        if (qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_IOPS_READ_MAX_LENGTH, 1) > UINT_MAX) {
+            error_setg(errp, "%s must be in the range [0, %u]",
+                       THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ_MAX_LENGTH,
+                       UINT_MAX);
+            return -1;
+        }
+        cfg->buckets[THROTTLE_OPS_READ].burst_length =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_IOPS_READ_MAX_LENGTH, 1);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE_MAX_LENGTH)) {
+        if (qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_IOPS_WRITE_MAX_LENGTH, 1) > UINT_MAX) {
+            error_setg(errp, "%s must be in the range [0, %u]",
+                       THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE_MAX_LENGTH,
+                       UINT_MAX);
+            return -1;
+        }
+        cfg->buckets[THROTTLE_OPS_WRITE].burst_length =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX
+                                QEMU_OPT_IOPS_WRITE_MAX_LENGTH, 1);
+    }
+    if (qemu_opt_get(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_SIZE)) {
+        cfg->op_size =
+            qemu_opt_get_number(opts, THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_SIZE,
+                                0);
+    }
+    return 0;
+}
+
+static int throttle_configure_tgm(BlockDriverState *bs,
+                                  ThrottleGroupMember *tgm,
+                                  QDict *options, Error **errp)
+{
+    int ret;
+    ThrottleConfig cfg;
+    const char *group_name = NULL;
+    Error *local_err = NULL;
+    QemuOpts *opts = qemu_opts_create(&throttle_opts, NULL, 0, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return -EINVAL;
+    }
+
+    qemu_opts_absorb_qdict(opts, options, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        goto err;
+    }
+
+    /* If no name is specified, an anonymous group will be created */
+    group_name = qemu_opt_get(opts, QEMU_OPT_THROTTLE_GROUP_NAME);
+
+    /* Register membership to group with name group_name */
+    throttle_group_register_tgm(tgm, group_name, bdrv_get_aio_context(bs));
+
+    /* Copy previous configuration */
+    throttle_group_get_config(tgm, &cfg);
+
+    /* Change limits if user has specified them */
+    if (throttle_extract_options(opts, &cfg, errp) ||
+        !throttle_is_valid(&cfg, errp)) {
+        throttle_group_unregister_tgm(tgm);
+        goto err;
+    }
+    /* Update group configuration */
+    throttle_group_config(tgm, &cfg);
+
+    ret = 0;
+    goto fin;
+
+err:
+    ret = -EINVAL;
+fin:
+    qemu_opts_del(opts);
+    return ret;
+}
+
+static int throttle_open(BlockDriverState *bs, QDict *options,
+                            int flags, Error **errp)
+{
+    ThrottleGroupMember *tgm = bs->opaque;
+
+    bs->file = bdrv_open_child(NULL, options, "file",
+                                    bs, &child_file, false, errp);
+    if (!bs->file) {
+        return -EINVAL;
+    }
+
+    return throttle_configure_tgm(bs, tgm, options, errp);
+}
+
+static void throttle_close(BlockDriverState *bs)
+{
+    ThrottleGroupMember *tgm = bs->opaque;
+    throttle_group_unregister_tgm(tgm);
+}
+
+
+static int64_t throttle_getlength(BlockDriverState *bs)
+{
+    return bdrv_getlength(bs->file->bs);
+}
+
+
+static int coroutine_fn throttle_co_preadv(BlockDriverState *bs,
+                                           uint64_t offset, uint64_t bytes,
+                                           QEMUIOVector *qiov, int flags)
+{
+
+    ThrottleGroupMember *tgm = bs->opaque;
+    throttle_group_co_io_limits_intercept(tgm, bytes, false);
+
+    return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
+}
+
+static int coroutine_fn throttle_co_pwritev(BlockDriverState *bs,
+                                            uint64_t offset, uint64_t bytes,
+                                            QEMUIOVector *qiov, int flags)
+{
+    ThrottleGroupMember *tgm = bs->opaque;
+    throttle_group_co_io_limits_intercept(tgm, bytes, true);
+
+    return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
+}
+
+static int coroutine_fn throttle_co_pwrite_zeroes(BlockDriverState *bs,
+        int64_t offset, int bytes, BdrvRequestFlags flags)
+{
+    ThrottleGroupMember *tgm = bs->opaque;
+    throttle_group_co_io_limits_intercept(tgm, bytes, true);
+
+    return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
+}
+
+static int coroutine_fn throttle_co_pdiscard(BlockDriverState *bs,
+        int64_t offset, int bytes)
+{
+    ThrottleGroupMember *tgm = bs->opaque;
+    throttle_group_co_io_limits_intercept(tgm, bytes, true);
+
+    return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
+}
+
+static int throttle_co_flush(BlockDriverState *bs)
+{
+    return bdrv_co_flush(bs->file->bs);
+}
+
+static void throttle_detach_aio_context(BlockDriverState *bs)
+{
+    ThrottleGroupMember *tgm = bs->opaque;
+    throttle_group_detach_aio_context(tgm);
+}
+
+static void throttle_attach_aio_context(BlockDriverState *bs,
+                                    AioContext *new_context)
+{
+    ThrottleGroupMember *tgm = bs->opaque;
+    throttle_group_attach_aio_context(tgm, new_context);
+}
+
+static int throttle_reopen_prepare(BDRVReopenState *reopen_state,
+                                      BlockReopenQueue *queue, Error **errp)
+{
+    ThrottleGroupMember *tgm = NULL;
+
+    assert(reopen_state != NULL);
+    assert(reopen_state->bs != NULL);
+
+    reopen_state->opaque = g_new0(ThrottleGroupMember, 1);
+    tgm = reopen_state->opaque;
+
+    return throttle_configure_tgm(reopen_state->bs, tgm, reopen_state->options,
+            errp);
+}
+
+static void throttle_reopen_commit(BDRVReopenState *state)
+{
+    ThrottleGroupMember *tgm = state->bs->opaque;
+
+    throttle_group_unregister_tgm(tgm);
+    g_free(state->bs->opaque);
+    state->bs->opaque = state->opaque;
+    state->opaque = NULL;
+}
+
+static void throttle_reopen_abort(BDRVReopenState *state)
+{
+    ThrottleGroupMember *tgm = state->opaque;
+
+    throttle_group_unregister_tgm(tgm);
+    g_free(state->opaque);
+    state->opaque = NULL;
+}
+
+static bool throttle_recurse_is_first_non_filter(BlockDriverState *bs,
+                                                 BlockDriverState *candidate)
+{
+    return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
+}
+
+static BlockDriver bdrv_throttle = {
+    .format_name                        =   "throttle",
+    .protocol_name                      =   "throttle",
+    .instance_size                      =   sizeof(ThrottleGroupMember),
+
+    .bdrv_file_open                     =   throttle_open,
+    .bdrv_close                         =   throttle_close,
+    .bdrv_co_flush                      =   throttle_co_flush,
+
+    .bdrv_child_perm                    =   bdrv_filter_default_perms,
+
+    .bdrv_getlength                     =   throttle_getlength,
+
+    .bdrv_co_preadv                     =   throttle_co_preadv,
+    .bdrv_co_pwritev                    =   throttle_co_pwritev,
+
+    .bdrv_co_pwrite_zeroes              =   throttle_co_pwrite_zeroes,
+    .bdrv_co_pdiscard                   =   throttle_co_pdiscard,
+
+    .bdrv_recurse_is_first_non_filter   =   throttle_recurse_is_first_non_filter,
+
+    .bdrv_attach_aio_context            =   throttle_attach_aio_context,
+    .bdrv_detach_aio_context            =   throttle_detach_aio_context,
+
+    .bdrv_reopen_prepare                =   throttle_reopen_prepare,
+    .bdrv_reopen_commit                 =   throttle_reopen_commit,
+    .bdrv_reopen_abort                  =   throttle_reopen_abort,
+
+    .is_filter                          =   true,
+};
+
+static void bdrv_throttle_init(void)
+{
+    bdrv_register(&bdrv_throttle);
+}
+
+block_init(bdrv_throttle_init);
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 \
-- 
2.11.0

  parent reply	other threads:[~2017-07-31  9:55 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-31  9:54 [Qemu-devel] [PATCH v3 0/7] add throttle block driver filter Manos Pitsidianakis
2017-07-31  9:54 ` [Qemu-devel] [PATCH v3 1/7] block: move ThrottleGroup membership to ThrottleGroupMember Manos Pitsidianakis
2017-08-04 11:59   ` Alberto Garcia
2017-07-31  9:54 ` [Qemu-devel] [PATCH v3 2/7] block: add aio_context field in ThrottleGroupMember Manos Pitsidianakis
2017-08-04 12:14   ` Alberto Garcia
2017-07-31  9:54 ` [Qemu-devel] [PATCH v3 3/7] block: tidy ThrottleGroupMember initializations Manos Pitsidianakis
2017-08-04 12:35   ` Alberto Garcia
2017-07-31  9:54 ` [Qemu-devel] [PATCH v3 4/7] block: convert ThrottleGroup to object with QOM Manos Pitsidianakis
2017-08-01 15:47   ` Stefan Hajnoczi
2017-08-01 16:49     ` Manos Pitsidianakis
2017-08-02 10:39       ` Stefan Hajnoczi
2017-08-02 10:57         ` Manos Pitsidianakis
2017-08-02 14:43           ` Stefan Hajnoczi
2017-08-03  8:08           ` Kevin Wolf
2017-08-03 10:53             ` Stefan Hajnoczi
2017-08-03 11:17               ` Kevin Wolf
2017-08-03 12:29                 ` Manos Pitsidianakis
2017-08-08 13:01           ` Alberto Garcia
2017-07-31  9:54 ` Manos Pitsidianakis [this message]
2017-08-01 16:14   ` [Qemu-devel] [PATCH v3 5/7] block: add throttle block filter driver Stefan Hajnoczi
2017-08-03  8:07   ` Kevin Wolf
2017-08-03 11:48     ` Manos Pitsidianakis
2017-08-03 12:05       ` Kevin Wolf
2017-08-03 11:58     ` Eric Blake
2017-08-03 13:56       ` Manos Pitsidianakis
2017-08-08 13:13   ` Alberto Garcia
2017-08-08 13:45     ` Manos Pitsidianakis
2017-08-08 14:53       ` Alberto Garcia
2017-08-08 14:56         ` Manos Pitsidianakis
2017-08-08 15:04           ` Alberto Garcia
2017-08-09  9:36             ` Manos Pitsidianakis
2017-08-09 12:36               ` Alberto Garcia
2017-08-09 13:42                 ` Manos Pitsidianakis
2017-08-09 14:45                   ` Alberto Garcia
2017-08-09 15:39                     ` Kevin Wolf
2017-08-14 12:15                       ` Manos Pitsidianakis
2017-07-31  9:54 ` [Qemu-devel] [PATCH v3 6/7] block: add BlockDevOptionsThrottle to QAPI Manos Pitsidianakis
2017-08-01 16:16   ` Stefan Hajnoczi
2017-07-31  9:54 ` [Qemu-devel] [PATCH v3 7/7] block: add throttle block filter driver interface tests Manos Pitsidianakis
2017-08-03  8:07   ` Kevin Wolf
2017-08-03 13:24     ` Manos Pitsidianakis
2017-08-03 13:32       ` Kevin Wolf
2017-08-03 13:52         ` Manos Pitsidianakis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170731095443.28211-6-el13635@mail.ntua.gr \
    --to=el13635@mail.ntua.gr \
    --cc=berto@igalia.com \
    --cc=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.