]>
Commit | Line | Data |
---|---|---|
b07d2367 WB |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
3 | Date: Thu, 15 Feb 2018 11:07:56 +0100 | |
4 | Subject: [PATCH] vma: add throttling options to drive mapping fifo protocol | |
5 | ||
6 | Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
7 | --- | |
8 | vma.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- | |
9 | 1 file changed, 73 insertions(+), 9 deletions(-) | |
10 | ||
11 | diff --git a/vma.c b/vma.c | |
12 | index 04915427c8..91ae14cdc3 100644 | |
13 | --- a/vma.c | |
14 | +++ b/vma.c | |
15 | @@ -18,7 +18,9 @@ | |
16 | #include "qemu-common.h" | |
17 | #include "qemu/error-report.h" | |
18 | #include "qemu/main-loop.h" | |
19 | +#include "qemu/cutils.h" | |
20 | #include "qapi/qmp/qstring.h" | |
21 | +#include "qapi/qmp/qint.h" | |
22 | #include "sysemu/char.h" /* qstring_from_str */ | |
23 | #include "sysemu/block-backend.h" | |
24 | ||
25 | @@ -133,9 +135,39 @@ typedef struct RestoreMap { | |
26 | char *devname; | |
27 | char *path; | |
28 | char *format; | |
29 | + uint64_t throttling_bps; | |
30 | + char *throttling_group; | |
31 | bool write_zero; | |
32 | } RestoreMap; | |
33 | ||
34 | +static bool try_parse_option(char **line, const char *optname, char **out, const char *inbuf) { | |
35 | + size_t optlen = strlen(optname); | |
36 | + if (strncmp(*line, optname, optlen) != 0 || (*line)[optlen] != '=') { | |
37 | + return false; | |
38 | + } | |
39 | + if (*out) { | |
40 | + g_error("read map failed - duplicate value for option '%s'", optname); | |
41 | + } | |
42 | + char *value = (*line) + optlen + 1; /* including a '=' */ | |
43 | + char *colon = strchr(value, ':'); | |
44 | + if (!colon) { | |
45 | + g_error("read map failed - option '%s' not terminated ('%s')", | |
46 | + optname, inbuf); | |
47 | + } | |
48 | + *line = colon+1; | |
49 | + *out = g_strndup(value, colon - value); | |
50 | + return true; | |
51 | +} | |
52 | + | |
53 | +static uint64_t verify_u64(const char *text) { | |
54 | + uint64_t value; | |
55 | + const char *endptr = NULL; | |
56 | + if (qemu_strtou64(text, &endptr, 0, &value) != 0 || !endptr || *endptr) { | |
57 | + g_error("read map failed - not a number: %s", text); | |
58 | + } | |
59 | + return value; | |
60 | +} | |
61 | + | |
62 | static int extract_content(int argc, char **argv) | |
63 | { | |
64 | int c, ret = 0; | |
65 | @@ -209,6 +241,9 @@ static int extract_content(int argc, char **argv) | |
66 | while (1) { | |
67 | char inbuf[8192]; | |
68 | char *line = fgets(inbuf, sizeof(inbuf), map); | |
69 | + char *format = NULL; | |
70 | + char *bps = NULL; | |
71 | + char *group = NULL; | |
72 | if (!line || line[0] == '\0' || !strcmp(line, "done\n")) { | |
73 | break; | |
74 | } | |
75 | @@ -220,15 +255,19 @@ static int extract_content(int argc, char **argv) | |
76 | } | |
77 | } | |
78 | ||
79 | - char *format = NULL; | |
80 | - if (strncmp(line, "format=", sizeof("format=")-1) == 0) { | |
81 | - format = line + sizeof("format=")-1; | |
82 | - char *colon = strchr(format, ':'); | |
83 | - if (!colon) { | |
84 | - g_error("read map failed - found only a format ('%s')", inbuf); | |
85 | + while (1) { | |
86 | + if (!try_parse_option(&line, "format", &format, inbuf) && | |
87 | + !try_parse_option(&line, "throttling.bps", &bps, inbuf) && | |
88 | + !try_parse_option(&line, "throttling.group", &group, inbuf)) | |
89 | + { | |
90 | + break; | |
91 | } | |
92 | - format = g_strndup(format, colon - format); | |
93 | - line = colon+1; | |
94 | + } | |
95 | + | |
96 | + uint64_t bps_value = 0; | |
97 | + if (bps) { | |
98 | + bps_value = verify_u64(bps); | |
99 | + g_free(bps); | |
100 | } | |
101 | ||
102 | const char *path; | |
103 | @@ -254,6 +293,8 @@ static int extract_content(int argc, char **argv) | |
104 | map->devname = g_strdup(devname); | |
105 | map->path = g_strdup(path); | |
106 | map->format = format; | |
107 | + map->throttling_bps = bps_value; | |
108 | + map->throttling_group = group; | |
109 | map->write_zero = write_zero; | |
110 | ||
111 | g_hash_table_insert(devmap, map->devname, map); | |
112 | @@ -281,6 +322,8 @@ static int extract_content(int argc, char **argv) | |
113 | } else if (di) { | |
114 | char *devfn = NULL; | |
115 | const char *format = NULL; | |
116 | + uint64_t throttling_bps = 0; | |
117 | + const char *throttling_group = NULL; | |
118 | int flags = BDRV_O_RDWR | BDRV_O_NO_FLUSH; | |
119 | bool write_zero = true; | |
120 | ||
121 | @@ -292,6 +335,8 @@ static int extract_content(int argc, char **argv) | |
122 | } | |
123 | devfn = map->path; | |
124 | format = map->format; | |
125 | + throttling_bps = map->throttling_bps; | |
126 | + throttling_group = map->throttling_group; | |
127 | write_zero = map->write_zero; | |
128 | } else { | |
129 | devfn = g_strdup_printf("%s/tmp-disk-%s.raw", | |
130 | @@ -328,12 +373,31 @@ static int extract_content(int argc, char **argv) | |
131 | qdict_put(options, "driver", qstring_from_str("raw")); | |
132 | } | |
133 | ||
134 | - | |
135 | if (errp || !(blk = blk_new_open(devfn, NULL, options, flags, &errp))) { | |
136 | g_error("can't open file %s - %s", devfn, | |
137 | error_get_pretty(errp)); | |
138 | } | |
139 | ||
140 | + if (throttling_group) { | |
141 | + blk_io_limits_enable(blk, throttling_group); | |
142 | + } | |
143 | + | |
144 | + if (throttling_bps) { | |
145 | + if (!throttling_group) { | |
146 | + blk_io_limits_enable(blk, devfn); | |
147 | + } | |
148 | + | |
149 | + ThrottleConfig cfg; | |
150 | + throttle_config_init(&cfg); | |
151 | + cfg.buckets[THROTTLE_BPS_WRITE].avg = throttling_bps; | |
152 | + Error *err = NULL; | |
153 | + if (!throttle_is_valid(&cfg, &err)) { | |
154 | + error_report_err(err); | |
155 | + g_error("failed to apply throttling"); | |
156 | + } | |
157 | + blk_set_io_limits(blk, &cfg); | |
158 | + } | |
159 | + | |
160 | if (vma_reader_register_bs(vmar, i, blk, write_zero, &errp) < 0) { | |
161 | g_error("%s", error_get_pretty(errp)); | |
162 | } | |
163 | -- | |
164 | 2.11.0 | |
165 |