throttle.c (c416eecea5f3aea863ab8fda5a36a24157b8f704) throttle.c (bc33c047d1ec0b35c9cd8be62bcefae2da28654f)
1/*
2 * QEMU block throttling filter driver infrastructure
3 *
4 * Copyright (c) 2017 Manos Pitsidianakis
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 or

--- 22 unchanged lines hidden (view full) ---

31 .name = QEMU_OPT_THROTTLE_GROUP_NAME,
32 .type = QEMU_OPT_STRING,
33 .help = "Name of the throttle group",
34 },
35 { /* end of list */ }
36 },
37};
38
1/*
2 * QEMU block throttling filter driver infrastructure
3 *
4 * Copyright (c) 2017 Manos Pitsidianakis
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 or

--- 22 unchanged lines hidden (view full) ---

31 .name = QEMU_OPT_THROTTLE_GROUP_NAME,
32 .type = QEMU_OPT_STRING,
33 .help = "Name of the throttle group",
34 },
35 { /* end of list */ }
36 },
37};
38
39static int throttle_configure_tgm(BlockDriverState *bs,
40 ThrottleGroupMember *tgm,
41 QDict *options, Error **errp)
39/*
40 * If this function succeeds then the throttle group name is stored in
41 * @group and must be freed by the caller.
42 * If there's an error then @group remains unmodified.
43 */
44static int throttle_parse_options(QDict *options, char **group, Error **errp)
42{
43 int ret;
44 const char *group_name;
45 Error *local_err = NULL;
46 QemuOpts *opts = qemu_opts_create(&throttle_opts, NULL, 0, &error_abort);
47
48 qemu_opts_absorb_qdict(opts, options, &local_err);
49 if (local_err) {

--- 8 unchanged lines hidden (view full) ---

58 ret = -EINVAL;
59 goto fin;
60 } else if (!throttle_group_exists(group_name)) {
61 error_setg(errp, "Throttle group '%s' does not exist", group_name);
62 ret = -EINVAL;
63 goto fin;
64 }
65
45{
46 int ret;
47 const char *group_name;
48 Error *local_err = NULL;
49 QemuOpts *opts = qemu_opts_create(&throttle_opts, NULL, 0, &error_abort);
50
51 qemu_opts_absorb_qdict(opts, options, &local_err);
52 if (local_err) {

--- 8 unchanged lines hidden (view full) ---

61 ret = -EINVAL;
62 goto fin;
63 } else if (!throttle_group_exists(group_name)) {
64 error_setg(errp, "Throttle group '%s' does not exist", group_name);
65 ret = -EINVAL;
66 goto fin;
67 }
68
66 /* Register membership to group with name group_name */
67 throttle_group_register_tgm(tgm, group_name, bdrv_get_aio_context(bs));
69 *group = g_strdup(group_name);
68 ret = 0;
69fin:
70 qemu_opts_del(opts);
71 return ret;
72}
73
74static int throttle_open(BlockDriverState *bs, QDict *options,
75 int flags, Error **errp)
76{
77 ThrottleGroupMember *tgm = bs->opaque;
70 ret = 0;
71fin:
72 qemu_opts_del(opts);
73 return ret;
74}
75
76static int throttle_open(BlockDriverState *bs, QDict *options,
77 int flags, Error **errp)
78{
79 ThrottleGroupMember *tgm = bs->opaque;
80 char *group;
81 int ret;
78
79 bs->file = bdrv_open_child(NULL, options, "file", bs,
80 &child_file, false, errp);
81 if (!bs->file) {
82 return -EINVAL;
83 }
84 bs->supported_write_flags = bs->file->bs->supported_write_flags |
85 BDRV_REQ_WRITE_UNCHANGED;
86 bs->supported_zero_flags = bs->file->bs->supported_zero_flags |
87 BDRV_REQ_WRITE_UNCHANGED;
88
82
83 bs->file = bdrv_open_child(NULL, options, "file", bs,
84 &child_file, false, errp);
85 if (!bs->file) {
86 return -EINVAL;
87 }
88 bs->supported_write_flags = bs->file->bs->supported_write_flags |
89 BDRV_REQ_WRITE_UNCHANGED;
90 bs->supported_zero_flags = bs->file->bs->supported_zero_flags |
91 BDRV_REQ_WRITE_UNCHANGED;
92
89 return throttle_configure_tgm(bs, tgm, options, errp);
93 ret = throttle_parse_options(options, &group, errp);
94 if (ret == 0) {
95 /* Register membership to group with name group_name */
96 throttle_group_register_tgm(tgm, group, bdrv_get_aio_context(bs));
97 g_free(group);
98 }
99
100 return ret;
90}
91
92static void throttle_close(BlockDriverState *bs)
93{
94 ThrottleGroupMember *tgm = bs->opaque;
95 throttle_group_unregister_tgm(tgm);
96}
97

--- 59 unchanged lines hidden (view full) ---

157{
158 ThrottleGroupMember *tgm = bs->opaque;
159 throttle_group_attach_aio_context(tgm, new_context);
160}
161
162static int throttle_reopen_prepare(BDRVReopenState *reopen_state,
163 BlockReopenQueue *queue, Error **errp)
164{
101}
102
103static void throttle_close(BlockDriverState *bs)
104{
105 ThrottleGroupMember *tgm = bs->opaque;
106 throttle_group_unregister_tgm(tgm);
107}
108

--- 59 unchanged lines hidden (view full) ---

168{
169 ThrottleGroupMember *tgm = bs->opaque;
170 throttle_group_attach_aio_context(tgm, new_context);
171}
172
173static int throttle_reopen_prepare(BDRVReopenState *reopen_state,
174 BlockReopenQueue *queue, Error **errp)
175{
165 ThrottleGroupMember *tgm;
176 int ret;
177 char *group = NULL;
166
167 assert(reopen_state != NULL);
168 assert(reopen_state->bs != NULL);
169
178
179 assert(reopen_state != NULL);
180 assert(reopen_state->bs != NULL);
181
170 reopen_state->opaque = g_new0(ThrottleGroupMember, 1);
171 tgm = reopen_state->opaque;
172
173 return throttle_configure_tgm(reopen_state->bs, tgm, reopen_state->options,
174 errp);
182 ret = throttle_parse_options(reopen_state->options, &group, errp);
183 reopen_state->opaque = group;
184 return ret;
175}
176
177static void throttle_reopen_commit(BDRVReopenState *reopen_state)
178{
185}
186
187static void throttle_reopen_commit(BDRVReopenState *reopen_state)
188{
179 ThrottleGroupMember *old_tgm = reopen_state->bs->opaque;
180 ThrottleGroupMember *new_tgm = reopen_state->opaque;
189 BlockDriverState *bs = reopen_state->bs;
190 ThrottleGroupMember *tgm = bs->opaque;
191 char *group = reopen_state->opaque;
181
192
182 throttle_group_unregister_tgm(old_tgm);
183 g_free(old_tgm);
184 reopen_state->bs->opaque = new_tgm;
193 assert(group);
194
195 if (strcmp(group, throttle_group_get_name(tgm))) {
196 throttle_group_unregister_tgm(tgm);
197 throttle_group_register_tgm(tgm, group, bdrv_get_aio_context(bs));
198 }
199 g_free(reopen_state->opaque);
185 reopen_state->opaque = NULL;
186}
187
188static void throttle_reopen_abort(BDRVReopenState *reopen_state)
189{
200 reopen_state->opaque = NULL;
201}
202
203static void throttle_reopen_abort(BDRVReopenState *reopen_state)
204{
190 ThrottleGroupMember *tgm = reopen_state->opaque;
191
192 throttle_group_unregister_tgm(tgm);
193 g_free(tgm);
205 g_free(reopen_state->opaque);
194 reopen_state->opaque = NULL;
195}
196
197static bool throttle_recurse_is_first_non_filter(BlockDriverState *bs,
198 BlockDriverState *candidate)
199{
200 return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
201}

--- 56 unchanged lines hidden ---
206 reopen_state->opaque = NULL;
207}
208
209static bool throttle_recurse_is_first_non_filter(BlockDriverState *bs,
210 BlockDriverState *candidate)
211{
212 return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
213}

--- 56 unchanged lines hidden ---