From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Thu, 15 Feb 2018 11:07:56 +0100 Subject: [PATCH] PVE: vma: add throttling options to drive mapping fifo protocol We now need to call initialize the qom module as well. Signed-off-by: Wolfgang Bumiller Signed-off-by: Thomas Lamprecht --- vma.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 12 deletions(-) diff --git a/vma.c b/vma.c index 1b59fd1555..f9f5c308fe 100644 --- a/vma.c +++ b/vma.c @@ -18,7 +18,8 @@ #include "qemu-common.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" -#include "qapi/qmp/qstring.h" +#include "qemu/cutils.h" +#include "qapi/qmp/qdict.h" #include "sysemu/block-backend.h" static void help(void) @@ -132,9 +133,39 @@ typedef struct RestoreMap { char *devname; char *path; char *format; + uint64_t throttling_bps; + char *throttling_group; bool write_zero; } RestoreMap; +static bool try_parse_option(char **line, const char *optname, char **out, const char *inbuf) { + size_t optlen = strlen(optname); + if (strncmp(*line, optname, optlen) != 0 || (*line)[optlen] != '=') { + return false; + } + if (*out) { + g_error("read map failed - duplicate value for option '%s'", optname); + } + char *value = (*line) + optlen + 1; /* including a '=' */ + char *colon = strchr(value, ':'); + if (!colon) { + g_error("read map failed - option '%s' not terminated ('%s')", + optname, inbuf); + } + *line = colon+1; + *out = g_strndup(value, colon - value); + return true; +} + +static uint64_t verify_u64(const char *text) { + uint64_t value; + const char *endptr = NULL; + if (qemu_strtou64(text, &endptr, 0, &value) != 0 || !endptr || *endptr) { + g_error("read map failed - not a number: %s", text); + } + return value; +} + static int extract_content(int argc, char **argv) { int c, ret = 0; @@ -208,6 +239,9 @@ static int extract_content(int argc, char **argv) while (1) { char inbuf[8192]; char *line = fgets(inbuf, sizeof(inbuf), map); + char *format = NULL; + char *bps = NULL; + char *group = NULL; if (!line || line[0] == '\0' || !strcmp(line, "done\n")) { break; } @@ -219,15 +253,19 @@ static int extract_content(int argc, char **argv) } } - char *format = NULL; - if (strncmp(line, "format=", sizeof("format=")-1) == 0) { - format = line + sizeof("format=")-1; - char *colon = strchr(format, ':'); - if (!colon) { - g_error("read map failed - found only a format ('%s')", inbuf); + while (1) { + if (!try_parse_option(&line, "format", &format, inbuf) && + !try_parse_option(&line, "throttling.bps", &bps, inbuf) && + !try_parse_option(&line, "throttling.group", &group, inbuf)) + { + break; } - format = g_strndup(format, colon - format); - line = colon+1; + } + + uint64_t bps_value = 0; + if (bps) { + bps_value = verify_u64(bps); + g_free(bps); } const char *path; @@ -253,6 +291,8 @@ static int extract_content(int argc, char **argv) map->devname = g_strdup(devname); map->path = g_strdup(path); map->format = format; + map->throttling_bps = bps_value; + map->throttling_group = group; map->write_zero = write_zero; g_hash_table_insert(devmap, map->devname, map); @@ -280,6 +320,8 @@ static int extract_content(int argc, char **argv) } else if (di) { char *devfn = NULL; const char *format = NULL; + uint64_t throttling_bps = 0; + const char *throttling_group = NULL; int flags = BDRV_O_RDWR | BDRV_O_NO_FLUSH; bool write_zero = true; @@ -291,6 +333,8 @@ static int extract_content(int argc, char **argv) } devfn = map->path; format = map->format; + throttling_bps = map->throttling_bps; + throttling_group = map->throttling_group; write_zero = map->write_zero; } else { devfn = g_strdup_printf("%s/tmp-disk-%s.raw", @@ -315,7 +359,7 @@ static int extract_content(int argc, char **argv) if (format) { /* explicit format from commandline */ options = qdict_new(); - qdict_put(options, "driver", qstring_from_str(format)); + qdict_put_str(options, "driver", format); } else if ((devlen > 4 && strcmp(devfn+devlen-4, ".raw") == 0) || strncmp(devfn, "/dev/", 5) == 0) { @@ -324,15 +368,34 @@ static int extract_content(int argc, char **argv) */ /* explicit raw format */ options = qdict_new(); - qdict_put(options, "driver", qstring_from_str("raw")); + qdict_put_str(options, "driver", "raw"); } - if (errp || !(blk = blk_new_open(devfn, NULL, options, flags, &errp))) { g_error("can't open file %s - %s", devfn, error_get_pretty(errp)); } + if (throttling_group) { + blk_io_limits_enable(blk, throttling_group); + } + + if (throttling_bps) { + if (!throttling_group) { + blk_io_limits_enable(blk, devfn); + } + + ThrottleConfig cfg; + throttle_config_init(&cfg); + cfg.buckets[THROTTLE_BPS_WRITE].avg = throttling_bps; + Error *err = NULL; + if (!throttle_is_valid(&cfg, &err)) { + error_report_err(err); + g_error("failed to apply throttling"); + } + blk_set_io_limits(blk, &cfg); + } + if (vma_reader_register_bs(vmar, i, blk, write_zero, &errp) < 0) { g_error("%s", error_get_pretty(errp)); } @@ -730,6 +793,7 @@ int main(int argc, char **argv) } bdrv_init(); + module_call_init(MODULE_INIT_QOM); if (argc < 2) { help(); -- 2.20.1