qemu/block/throttle-groups.c
<<
>>
Prefs
   1/*
   2 * QEMU block throttling group infrastructure
   3 *
   4 * Copyright (C) Nodalink, EURL. 2014
   5 * Copyright (C) Igalia, S.L. 2015
   6 *
   7 * Authors:
   8 *   BenoƮt Canet <benoit.canet@nodalink.com>
   9 *   Alberto Garcia <berto@igalia.com>
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 or
  14 * (at your option) version 3 of the License.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
  23 */
  24
  25#include "qemu/osdep.h"
  26#include "sysemu/block-backend.h"
  27#include "block/throttle-groups.h"
  28#include "qemu/throttle-options.h"
  29#include "qemu/main-loop.h"
  30#include "qemu/queue.h"
  31#include "qemu/thread.h"
  32#include "sysemu/qtest.h"
  33#include "qapi/error.h"
  34#include "qapi/qapi-visit-block-core.h"
  35#include "qom/object.h"
  36#include "qom/object_interfaces.h"
  37
  38static void throttle_group_obj_init(Object *obj);
  39static void throttle_group_obj_complete(UserCreatable *obj, Error **errp);
  40static void timer_cb(ThrottleGroupMember *tgm, bool is_write);
  41
  42/* The ThrottleGroup structure (with its ThrottleState) is shared
  43 * among different ThrottleGroupMembers and it's independent from
  44 * AioContext, so in order to use it from different threads it needs
  45 * its own locking.
  46 *
  47 * This locking is however handled internally in this file, so it's
  48 * transparent to outside users.
  49 *
  50 * The whole ThrottleGroup structure is private and invisible to
  51 * outside users, that only use it through its ThrottleState.
  52 *
  53 * In addition to the ThrottleGroup structure, ThrottleGroupMember has
  54 * fields that need to be accessed by other members of the group and
  55 * therefore also need to be protected by this lock. Once a
  56 * ThrottleGroupMember is registered in a group those fields can be accessed
  57 * by other threads any time.
  58 *
  59 * Again, all this is handled internally and is mostly transparent to
  60 * the outside. The 'throttle_timers' field however has an additional
  61 * constraint because it may be temporarily invalid (see for example
  62 * blk_set_aio_context()). Therefore in this file a thread will
  63 * access some other ThrottleGroupMember's timers only after verifying that
  64 * that ThrottleGroupMember has throttled requests in the queue.
  65 */
  66struct ThrottleGroup {
  67    Object parent_obj;
  68
  69    /* refuse individual property change if initialization is complete */
  70    bool is_initialized;
  71    char *name; /* This is constant during the lifetime of the group */
  72
  73    QemuMutex lock; /* This lock protects the following four fields */
  74    ThrottleState ts;
  75    QLIST_HEAD(, ThrottleGroupMember) head;
  76    ThrottleGroupMember *tokens[2];
  77    bool any_timer_armed[2];
  78    QEMUClockType clock_type;
  79
  80    /* This field is protected by the global QEMU mutex */
  81    QTAILQ_ENTRY(ThrottleGroup) list;
  82};
  83
  84/* This is protected by the global QEMU mutex */
  85static QTAILQ_HEAD(, ThrottleGroup) throttle_groups =
  86    QTAILQ_HEAD_INITIALIZER(throttle_groups);
  87
  88
  89/* This function reads throttle_groups and must be called under the global
  90 * mutex.
  91 */
  92static ThrottleGroup *throttle_group_by_name(const char *name)
  93{
  94    ThrottleGroup *iter;
  95
  96    /* Look for an existing group with that name */
  97    QTAILQ_FOREACH(iter, &throttle_groups, list) {
  98        if (!g_strcmp0(name, iter->name)) {
  99            return iter;
 100        }
 101    }
 102
 103    return NULL;
 104}
 105
 106/* This function reads throttle_groups and must be called under the global
 107 * mutex.
 108 */
 109bool throttle_group_exists(const char *name)
 110{
 111    return throttle_group_by_name(name) != NULL;
 112}
 113
 114/* Increments the reference count of a ThrottleGroup given its name.
 115 *
 116 * If no ThrottleGroup is found with the given name a new one is
 117 * created.
 118 *
 119 * This function edits throttle_groups and must be called under the global
 120 * mutex.
 121 *
 122 * @name: the name of the ThrottleGroup
 123 * @ret:  the ThrottleState member of the ThrottleGroup
 124 */
 125ThrottleState *throttle_group_incref(const char *name)
 126{
 127    ThrottleGroup *tg = NULL;
 128
 129    /* Look for an existing group with that name */
 130    tg = throttle_group_by_name(name);
 131
 132    if (tg) {
 133        object_ref(OBJECT(tg));
 134    } else {
 135        /* Create a new one if not found */
 136        /* new ThrottleGroup obj will have a refcnt = 1 */
 137        tg = THROTTLE_GROUP(object_new(TYPE_THROTTLE_GROUP));
 138        tg->name = g_strdup(name);
 139        throttle_group_obj_complete(USER_CREATABLE(tg), &error_abort);
 140    }
 141
 142    return &tg->ts;
 143}
 144
 145/* Decrease the reference count of a ThrottleGroup.
 146 *
 147 * When the reference count reaches zero the ThrottleGroup is
 148 * destroyed.
 149 *
 150 * This function edits throttle_groups and must be called under the global
 151 * mutex.
 152 *
 153 * @ts:  The ThrottleGroup to unref, given by its ThrottleState member
 154 */
 155void throttle_group_unref(ThrottleState *ts)
 156{
 157    ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
 158    object_unref(OBJECT(tg));
 159}
 160
 161/* Get the name from a ThrottleGroupMember's group. The name (and the pointer)
 162 * is guaranteed to remain constant during the lifetime of the group.
 163 *
 164 * @tgm:  a ThrottleGroupMember
 165 * @ret:  the name of the group.
 166 */
 167const char *throttle_group_get_name(ThrottleGroupMember *tgm)
 168{
 169    ThrottleGroup *tg = container_of(tgm->throttle_state, ThrottleGroup, ts);
 170    return tg->name;
 171}
 172
 173/* Return the next ThrottleGroupMember in the round-robin sequence, simulating
 174 * a circular list.
 175 *
 176 * This assumes that tg->lock is held.
 177 *
 178 * @tgm: the current ThrottleGroupMember
 179 * @ret: the next ThrottleGroupMember in the sequence
 180 */
 181static ThrottleGroupMember *throttle_group_next_tgm(ThrottleGroupMember *tgm)
 182{
 183    ThrottleState *ts = tgm->throttle_state;
 184    ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
 185    ThrottleGroupMember *next = QLIST_NEXT(tgm, round_robin);
 186
 187    if (!next) {
 188        next = QLIST_FIRST(&tg->head);
 189    }
 190
 191    return next;
 192}
 193
 194/*
 195 * Return whether a ThrottleGroupMember has pending requests.
 196 *
 197 * This assumes that tg->lock is held.
 198 *
 199 * @tgm:        the ThrottleGroupMember
 200 * @is_write:   the type of operation (read/write)
 201 * @ret:        whether the ThrottleGroupMember has pending requests.
 202 */
 203static inline bool tgm_has_pending_reqs(ThrottleGroupMember *tgm,
 204                                        bool is_write)
 205{
 206    return tgm->pending_reqs[is_write];
 207}
 208
 209/* Return the next ThrottleGroupMember in the round-robin sequence with pending
 210 * I/O requests.
 211 *
 212 * This assumes that tg->lock is held.
 213 *
 214 * @tgm:       the current ThrottleGroupMember
 215 * @is_write:  the type of operation (read/write)
 216 * @ret:       the next ThrottleGroupMember with pending requests, or tgm if
 217 *             there is none.
 218 */
 219static ThrottleGroupMember *next_throttle_token(ThrottleGroupMember *tgm,
 220                                                bool is_write)
 221{
 222    ThrottleState *ts = tgm->throttle_state;
 223    ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
 224    ThrottleGroupMember *token, *start;
 225
 226    /* If this member has its I/O limits disabled then it means that
 227     * it's being drained. Skip the round-robin search and return tgm
 228     * immediately if it has pending requests. Otherwise we could be
 229     * forcing it to wait for other member's throttled requests. */
 230    if (tgm_has_pending_reqs(tgm, is_write) &&
 231        qatomic_read(&tgm->io_limits_disabled)) {
 232        return tgm;
 233    }
 234
 235    start = token = tg->tokens[is_write];
 236
 237    /* get next bs round in round robin style */
 238    token = throttle_group_next_tgm(token);
 239    while (token != start && !tgm_has_pending_reqs(token, is_write)) {
 240        token = throttle_group_next_tgm(token);
 241    }
 242
 243    /* If no IO are queued for scheduling on the next round robin token
 244     * then decide the token is the current tgm because chances are
 245     * the current tgm got the current request queued.
 246     */
 247    if (token == start && !tgm_has_pending_reqs(token, is_write)) {
 248        token = tgm;
 249    }
 250
 251    /* Either we return the original TGM, or one with pending requests */
 252    assert(token == tgm || tgm_has_pending_reqs(token, is_write));
 253
 254    return token;
 255}
 256
 257/* Check if the next I/O request for a ThrottleGroupMember needs to be
 258 * throttled or not. If there's no timer set in this group, set one and update
 259 * the token accordingly.
 260 *
 261 * This assumes that tg->lock is held.
 262 *
 263 * @tgm:        the current ThrottleGroupMember
 264 * @is_write:   the type of operation (read/write)
 265 * @ret:        whether the I/O request needs to be throttled or not
 266 */
 267static bool throttle_group_schedule_timer(ThrottleGroupMember *tgm,
 268                                          bool is_write)
 269{
 270    ThrottleState *ts = tgm->throttle_state;
 271    ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
 272    ThrottleTimers *tt = &tgm->throttle_timers;
 273    bool must_wait;
 274
 275    if (qatomic_read(&tgm->io_limits_disabled)) {
 276        return false;
 277    }
 278
 279    /* Check if any of the timers in this group is already armed */
 280    if (tg->any_timer_armed[is_write]) {
 281        return true;
 282    }
 283
 284    must_wait = throttle_schedule_timer(ts, tt, is_write);
 285
 286    /* If a timer just got armed, set tgm as the current token */
 287    if (must_wait) {
 288        tg->tokens[is_write] = tgm;
 289        tg->any_timer_armed[is_write] = true;
 290    }
 291
 292    return must_wait;
 293}
 294
 295/* Start the next pending I/O request for a ThrottleGroupMember. Return whether
 296 * any request was actually pending.
 297 *
 298 * @tgm:       the current ThrottleGroupMember
 299 * @is_write:  the type of operation (read/write)
 300 */
 301static bool coroutine_fn throttle_group_co_restart_queue(ThrottleGroupMember *tgm,
 302                                                         bool is_write)
 303{
 304    bool ret;
 305
 306    qemu_co_mutex_lock(&tgm->throttled_reqs_lock);
 307    ret = qemu_co_queue_next(&tgm->throttled_reqs[is_write]);
 308    qemu_co_mutex_unlock(&tgm->throttled_reqs_lock);
 309
 310    return ret;
 311}
 312
 313/* Look for the next pending I/O request and schedule it.
 314 *
 315 * This assumes that tg->lock is held.
 316 *
 317 * @tgm:       the current ThrottleGroupMember
 318 * @is_write:  the type of operation (read/write)
 319 */
 320static void schedule_next_request(ThrottleGroupMember *tgm, bool is_write)
 321{
 322    ThrottleState *ts = tgm->throttle_state;
 323    ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
 324    bool must_wait;
 325    ThrottleGroupMember *token;
 326
 327    /* Check if there's any pending request to schedule next */
 328    token = next_throttle_token(tgm, is_write);
 329    if (!tgm_has_pending_reqs(token, is_write)) {
 330        return;
 331    }
 332
 333    /* Set a timer for the request if it needs to be throttled */
 334    must_wait = throttle_group_schedule_timer(token, is_write);
 335
 336    /* If it doesn't have to wait, queue it for immediate execution */
 337    if (!must_wait) {
 338        /* Give preference to requests from the current tgm */
 339        if (qemu_in_coroutine() &&
 340            throttle_group_co_restart_queue(tgm, is_write)) {
 341            token = tgm;
 342        } else {
 343            ThrottleTimers *tt = &token->throttle_timers;
 344            int64_t now = qemu_clock_get_ns(tg->clock_type);
 345            timer_mod(tt->timers[is_write], now);
 346            tg->any_timer_armed[is_write] = true;
 347        }
 348        tg->tokens[is_write] = token;
 349    }
 350}
 351
 352/* Check if an I/O request needs to be throttled, wait and set a timer
 353 * if necessary, and schedule the next request using a round robin
 354 * algorithm.
 355 *
 356 * @tgm:       the current ThrottleGroupMember
 357 * @bytes:     the number of bytes for this I/O
 358 * @is_write:  the type of operation (read/write)
 359 */
 360void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
 361                                                        int64_t bytes,
 362                                                        bool is_write)
 363{
 364    bool must_wait;
 365    ThrottleGroupMember *token;
 366    ThrottleGroup *tg = container_of(tgm->throttle_state, ThrottleGroup, ts);
 367
 368    assert(bytes >= 0);
 369
 370    qemu_mutex_lock(&tg->lock);
 371
 372    /* First we check if this I/O has to be throttled. */
 373    token = next_throttle_token(tgm, is_write);
 374    must_wait = throttle_group_schedule_timer(token, is_write);
 375
 376    /* Wait if there's a timer set or queued requests of this type */
 377    if (must_wait || tgm->pending_reqs[is_write]) {
 378        tgm->pending_reqs[is_write]++;
 379        qemu_mutex_unlock(&tg->lock);
 380        qemu_co_mutex_lock(&tgm->throttled_reqs_lock);
 381        qemu_co_queue_wait(&tgm->throttled_reqs[is_write],
 382                           &tgm->throttled_reqs_lock);
 383        qemu_co_mutex_unlock(&tgm->throttled_reqs_lock);
 384        qemu_mutex_lock(&tg->lock);
 385        tgm->pending_reqs[is_write]--;
 386    }
 387
 388    /* The I/O will be executed, so do the accounting */
 389    throttle_account(tgm->throttle_state, is_write, bytes);
 390
 391    /* Schedule the next request */
 392    schedule_next_request(tgm, is_write);
 393
 394    qemu_mutex_unlock(&tg->lock);
 395}
 396
 397typedef struct {
 398    ThrottleGroupMember *tgm;
 399    bool is_write;
 400} RestartData;
 401
 402static void coroutine_fn throttle_group_restart_queue_entry(void *opaque)
 403{
 404    RestartData *data = opaque;
 405    ThrottleGroupMember *tgm = data->tgm;
 406    ThrottleState *ts = tgm->throttle_state;
 407    ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
 408    bool is_write = data->is_write;
 409    bool empty_queue;
 410
 411    empty_queue = !throttle_group_co_restart_queue(tgm, is_write);
 412
 413    /* If the request queue was empty then we have to take care of
 414     * scheduling the next one */
 415    if (empty_queue) {
 416        qemu_mutex_lock(&tg->lock);
 417        schedule_next_request(tgm, is_write);
 418        qemu_mutex_unlock(&tg->lock);
 419    }
 420
 421    g_free(data);
 422
 423    qatomic_dec(&tgm->restart_pending);
 424    aio_wait_kick();
 425}
 426
 427static void throttle_group_restart_queue(ThrottleGroupMember *tgm, bool is_write)
 428{
 429    Coroutine *co;
 430    RestartData *rd = g_new0(RestartData, 1);
 431
 432    rd->tgm = tgm;
 433    rd->is_write = is_write;
 434
 435    /* This function is called when a timer is fired or when
 436     * throttle_group_restart_tgm() is called. Either way, there can
 437     * be no timer pending on this tgm at this point */
 438    assert(!timer_pending(tgm->throttle_timers.timers[is_write]));
 439
 440    qatomic_inc(&tgm->restart_pending);
 441
 442    co = qemu_coroutine_create(throttle_group_restart_queue_entry, rd);
 443    aio_co_enter(tgm->aio_context, co);
 444}
 445
 446void throttle_group_restart_tgm(ThrottleGroupMember *tgm)
 447{
 448    int i;
 449
 450    if (tgm->throttle_state) {
 451        for (i = 0; i < 2; i++) {
 452            QEMUTimer *t = tgm->throttle_timers.timers[i];
 453            if (timer_pending(t)) {
 454                /* If there's a pending timer on this tgm, fire it now */
 455                timer_del(t);
 456                timer_cb(tgm, i);
 457            } else {
 458                /* Else run the next request from the queue manually */
 459                throttle_group_restart_queue(tgm, i);
 460            }
 461        }
 462    }
 463}
 464
 465/* Update the throttle configuration for a particular group. Similar
 466 * to throttle_config(), but guarantees atomicity within the
 467 * throttling group.
 468 *
 469 * @tgm:    a ThrottleGroupMember that is a member of the group
 470 * @cfg: the configuration to set
 471 */
 472void throttle_group_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg)
 473{
 474    ThrottleState *ts = tgm->throttle_state;
 475    ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
 476    qemu_mutex_lock(&tg->lock);
 477    throttle_config(ts, tg->clock_type, cfg);
 478    qemu_mutex_unlock(&tg->lock);
 479
 480    throttle_group_restart_tgm(tgm);
 481}
 482
 483/* Get the throttle configuration from a particular group. Similar to
 484 * throttle_get_config(), but guarantees atomicity within the
 485 * throttling group.
 486 *
 487 * @tgm:    a ThrottleGroupMember that is a member of the group
 488 * @cfg: the configuration will be written here
 489 */
 490void throttle_group_get_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg)
 491{
 492    ThrottleState *ts = tgm->throttle_state;
 493    ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
 494    qemu_mutex_lock(&tg->lock);
 495    throttle_get_config(ts, cfg);
 496    qemu_mutex_unlock(&tg->lock);
 497}
 498
 499/* ThrottleTimers callback. This wakes up a request that was waiting
 500 * because it had been throttled.
 501 *
 502 * @tgm:       the ThrottleGroupMember whose request had been throttled
 503 * @is_write:  the type of operation (read/write)
 504 */
 505static void timer_cb(ThrottleGroupMember *tgm, bool is_write)
 506{
 507    ThrottleState *ts = tgm->throttle_state;
 508    ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
 509
 510    /* The timer has just been fired, so we can update the flag */
 511    qemu_mutex_lock(&tg->lock);
 512    tg->any_timer_armed[is_write] = false;
 513    qemu_mutex_unlock(&tg->lock);
 514
 515    /* Run the request that was waiting for this timer */
 516    throttle_group_restart_queue(tgm, is_write);
 517}
 518
 519static void read_timer_cb(void *opaque)
 520{
 521    timer_cb(opaque, false);
 522}
 523
 524static void write_timer_cb(void *opaque)
 525{
 526    timer_cb(opaque, true);
 527}
 528
 529/* Register a ThrottleGroupMember from the throttling group, also initializing
 530 * its timers and updating its throttle_state pointer to point to it. If a
 531 * throttling group with that name does not exist yet, it will be created.
 532 *
 533 * This function edits throttle_groups and must be called under the global
 534 * mutex.
 535 *
 536 * @tgm:       the ThrottleGroupMember to insert
 537 * @groupname: the name of the group
 538 * @ctx:       the AioContext to use
 539 */
 540void throttle_group_register_tgm(ThrottleGroupMember *tgm,
 541                                 const char *groupname,
 542                                 AioContext *ctx)
 543{
 544    int i;
 545    ThrottleState *ts = throttle_group_incref(groupname);
 546    ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
 547
 548    tgm->throttle_state = ts;
 549    tgm->aio_context = ctx;
 550    qatomic_set(&tgm->restart_pending, 0);
 551
 552    QEMU_LOCK_GUARD(&tg->lock);
 553    /* If the ThrottleGroup is new set this ThrottleGroupMember as the token */
 554    for (i = 0; i < 2; i++) {
 555        if (!tg->tokens[i]) {
 556            tg->tokens[i] = tgm;
 557        }
 558    }
 559
 560    QLIST_INSERT_HEAD(&tg->head, tgm, round_robin);
 561
 562    throttle_timers_init(&tgm->throttle_timers,
 563                         tgm->aio_context,
 564                         tg->clock_type,
 565                         read_timer_cb,
 566                         write_timer_cb,
 567                         tgm);
 568    qemu_co_mutex_init(&tgm->throttled_reqs_lock);
 569    qemu_co_queue_init(&tgm->throttled_reqs[0]);
 570    qemu_co_queue_init(&tgm->throttled_reqs[1]);
 571}
 572
 573/* Unregister a ThrottleGroupMember from its group, removing it from the list,
 574 * destroying the timers and setting the throttle_state pointer to NULL.
 575 *
 576 * The ThrottleGroupMember must not have pending throttled requests, so the
 577 * caller has to drain them first.
 578 *
 579 * The group will be destroyed if it's empty after this operation.
 580 *
 581 * @tgm the ThrottleGroupMember to remove
 582 */
 583void throttle_group_unregister_tgm(ThrottleGroupMember *tgm)
 584{
 585    ThrottleState *ts = tgm->throttle_state;
 586    ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
 587    ThrottleGroupMember *token;
 588    int i;
 589
 590    if (!ts) {
 591        /* Discard already unregistered tgm */
 592        return;
 593    }
 594
 595    /* Wait for throttle_group_restart_queue_entry() coroutines to finish */
 596    AIO_WAIT_WHILE(tgm->aio_context, qatomic_read(&tgm->restart_pending) > 0);
 597
 598    WITH_QEMU_LOCK_GUARD(&tg->lock) {
 599        for (i = 0; i < 2; i++) {
 600            assert(tgm->pending_reqs[i] == 0);
 601            assert(qemu_co_queue_empty(&tgm->throttled_reqs[i]));
 602            assert(!timer_pending(tgm->throttle_timers.timers[i]));
 603            if (tg->tokens[i] == tgm) {
 604                token = throttle_group_next_tgm(tgm);
 605                /* Take care of the case where this is the last tgm in the group */
 606                if (token == tgm) {
 607                    token = NULL;
 608                }
 609                tg->tokens[i] = token;
 610            }
 611        }
 612
 613        /* remove the current tgm from the list */
 614        QLIST_REMOVE(tgm, round_robin);
 615        throttle_timers_destroy(&tgm->throttle_timers);
 616    }
 617
 618    throttle_group_unref(&tg->ts);
 619    tgm->throttle_state = NULL;
 620}
 621
 622void throttle_group_attach_aio_context(ThrottleGroupMember *tgm,
 623                                       AioContext *new_context)
 624{
 625    ThrottleTimers *tt = &tgm->throttle_timers;
 626    throttle_timers_attach_aio_context(tt, new_context);
 627    tgm->aio_context = new_context;
 628}
 629
 630void throttle_group_detach_aio_context(ThrottleGroupMember *tgm)
 631{
 632    ThrottleGroup *tg = container_of(tgm->throttle_state, ThrottleGroup, ts);
 633    ThrottleTimers *tt = &tgm->throttle_timers;
 634    int i;
 635
 636    /* Requests must have been drained */
 637    assert(tgm->pending_reqs[0] == 0 && tgm->pending_reqs[1] == 0);
 638    assert(qemu_co_queue_empty(&tgm->throttled_reqs[0]));
 639    assert(qemu_co_queue_empty(&tgm->throttled_reqs[1]));
 640
 641    /* Kick off next ThrottleGroupMember, if necessary */
 642    WITH_QEMU_LOCK_GUARD(&tg->lock) {
 643        for (i = 0; i < 2; i++) {
 644            if (timer_pending(tt->timers[i])) {
 645                tg->any_timer_armed[i] = false;
 646                schedule_next_request(tgm, i);
 647            }
 648        }
 649    }
 650
 651    throttle_timers_detach_aio_context(tt);
 652    tgm->aio_context = NULL;
 653}
 654
 655#undef THROTTLE_OPT_PREFIX
 656#define THROTTLE_OPT_PREFIX "x-"
 657
 658/* Helper struct and array for QOM property setter/getter */
 659typedef struct {
 660    const char *name;
 661    BucketType type;
 662    enum {
 663        AVG,
 664        MAX,
 665        BURST_LENGTH,
 666        IOPS_SIZE,
 667    } category;
 668} ThrottleParamInfo;
 669
 670static ThrottleParamInfo properties[] = {
 671    {
 672        THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL,
 673        THROTTLE_OPS_TOTAL, AVG,
 674    },
 675    {
 676        THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL_MAX,
 677        THROTTLE_OPS_TOTAL, MAX,
 678    },
 679    {
 680        THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_TOTAL_MAX_LENGTH,
 681        THROTTLE_OPS_TOTAL, BURST_LENGTH,
 682    },
 683    {
 684        THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ,
 685        THROTTLE_OPS_READ, AVG,
 686    },
 687    {
 688        THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ_MAX,
 689        THROTTLE_OPS_READ, MAX,
 690    },
 691    {
 692        THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_READ_MAX_LENGTH,
 693        THROTTLE_OPS_READ, BURST_LENGTH,
 694    },
 695    {
 696        THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE,
 697        THROTTLE_OPS_WRITE, AVG,
 698    },
 699    {
 700        THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE_MAX,
 701        THROTTLE_OPS_WRITE, MAX,
 702    },
 703    {
 704        THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_WRITE_MAX_LENGTH,
 705        THROTTLE_OPS_WRITE, BURST_LENGTH,
 706    },
 707    {
 708        THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL,
 709        THROTTLE_BPS_TOTAL, AVG,
 710    },
 711    {
 712        THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL_MAX,
 713        THROTTLE_BPS_TOTAL, MAX,
 714    },
 715    {
 716        THROTTLE_OPT_PREFIX QEMU_OPT_BPS_TOTAL_MAX_LENGTH,
 717        THROTTLE_BPS_TOTAL, BURST_LENGTH,
 718    },
 719    {
 720        THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ,
 721        THROTTLE_BPS_READ, AVG,
 722    },
 723    {
 724        THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ_MAX,
 725        THROTTLE_BPS_READ, MAX,
 726    },
 727    {
 728        THROTTLE_OPT_PREFIX QEMU_OPT_BPS_READ_MAX_LENGTH,
 729        THROTTLE_BPS_READ, BURST_LENGTH,
 730    },
 731    {
 732        THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE,
 733        THROTTLE_BPS_WRITE, AVG,
 734    },
 735    {
 736        THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE_MAX,
 737        THROTTLE_BPS_WRITE, MAX,
 738    },
 739    {
 740        THROTTLE_OPT_PREFIX QEMU_OPT_BPS_WRITE_MAX_LENGTH,
 741        THROTTLE_BPS_WRITE, BURST_LENGTH,
 742    },
 743    {
 744        THROTTLE_OPT_PREFIX QEMU_OPT_IOPS_SIZE,
 745        0, IOPS_SIZE,
 746    }
 747};
 748
 749/* This function edits throttle_groups and must be called under the global
 750 * mutex */
 751static void throttle_group_obj_init(Object *obj)
 752{
 753    ThrottleGroup *tg = THROTTLE_GROUP(obj);
 754
 755    tg->clock_type = QEMU_CLOCK_REALTIME;
 756    if (qtest_enabled()) {
 757        /* For testing block IO throttling only */
 758        tg->clock_type = QEMU_CLOCK_VIRTUAL;
 759    }
 760    tg->is_initialized = false;
 761    qemu_mutex_init(&tg->lock);
 762    throttle_init(&tg->ts);
 763    QLIST_INIT(&tg->head);
 764}
 765
 766/* This function edits throttle_groups and must be called under the global
 767 * mutex */
 768static void throttle_group_obj_complete(UserCreatable *obj, Error **errp)
 769{
 770    ThrottleGroup *tg = THROTTLE_GROUP(obj);
 771    ThrottleConfig cfg;
 772
 773    /* set group name to object id if it exists */
 774    if (!tg->name && tg->parent_obj.parent) {
 775        tg->name = g_strdup(object_get_canonical_path_component(OBJECT(obj)));
 776    }
 777    /* We must have a group name at this point */
 778    assert(tg->name);
 779
 780    /* error if name is duplicate */
 781    if (throttle_group_exists(tg->name)) {
 782        error_setg(errp, "A group with this name already exists");
 783        return;
 784    }
 785
 786    /* check validity */
 787    throttle_get_config(&tg->ts, &cfg);
 788    if (!throttle_is_valid(&cfg, errp)) {
 789        return;
 790    }
 791    throttle_config(&tg->ts, tg->clock_type, &cfg);
 792    QTAILQ_INSERT_TAIL(&throttle_groups, tg, list);
 793    tg->is_initialized = true;
 794}
 795
 796/* This function edits throttle_groups and must be called under the global
 797 * mutex */
 798static void throttle_group_obj_finalize(Object *obj)
 799{
 800    ThrottleGroup *tg = THROTTLE_GROUP(obj);
 801    if (tg->is_initialized) {
 802        QTAILQ_REMOVE(&throttle_groups, tg, list);
 803    }
 804    qemu_mutex_destroy(&tg->lock);
 805    g_free(tg->name);
 806}
 807
 808static void throttle_group_set(Object *obj, Visitor *v, const char * name,
 809                               void *opaque, Error **errp)
 810
 811{
 812    ThrottleGroup *tg = THROTTLE_GROUP(obj);
 813    ThrottleConfig *cfg;
 814    ThrottleParamInfo *info = opaque;
 815    int64_t value;
 816
 817    /* If we have finished initialization, don't accept individual property
 818     * changes through QOM. Throttle configuration limits must be set in one
 819     * transaction, as certain combinations are invalid.
 820     */
 821    if (tg->is_initialized) {
 822        error_setg(errp, "Property cannot be set after initialization");
 823        return;
 824    }
 825
 826    if (!visit_type_int64(v, name, &value, errp)) {
 827        return;
 828    }
 829    if (value < 0) {
 830        error_setg(errp, "Property values cannot be negative");
 831        return;
 832    }
 833
 834    cfg = &tg->ts.cfg;
 835    switch (info->category) {
 836    case AVG:
 837        cfg->buckets[info->type].avg = value;
 838        break;
 839    case MAX:
 840        cfg->buckets[info->type].max = value;
 841        break;
 842    case BURST_LENGTH:
 843        if (value > UINT_MAX) {
 844            error_setg(errp, "%s value must be in the" "range [0, %u]",
 845                       info->name, UINT_MAX);
 846            return;
 847        }
 848        cfg->buckets[info->type].burst_length = value;
 849        break;
 850    case IOPS_SIZE:
 851        cfg->op_size = value;
 852        break;
 853    }
 854}
 855
 856static void throttle_group_get(Object *obj, Visitor *v, const char *name,
 857                               void *opaque, Error **errp)
 858{
 859    ThrottleGroup *tg = THROTTLE_GROUP(obj);
 860    ThrottleConfig cfg;
 861    ThrottleParamInfo *info = opaque;
 862    int64_t value;
 863
 864    throttle_get_config(&tg->ts, &cfg);
 865    switch (info->category) {
 866    case AVG:
 867        value = cfg.buckets[info->type].avg;
 868        break;
 869    case MAX:
 870        value = cfg.buckets[info->type].max;
 871        break;
 872    case BURST_LENGTH:
 873        value = cfg.buckets[info->type].burst_length;
 874        break;
 875    case IOPS_SIZE:
 876        value = cfg.op_size;
 877        break;
 878    }
 879
 880    visit_type_int64(v, name, &value, errp);
 881}
 882
 883static void throttle_group_set_limits(Object *obj, Visitor *v,
 884                                      const char *name, void *opaque,
 885                                      Error **errp)
 886
 887{
 888    ThrottleGroup *tg = THROTTLE_GROUP(obj);
 889    ThrottleConfig cfg;
 890    ThrottleLimits *argp;
 891    Error *local_err = NULL;
 892
 893    if (!visit_type_ThrottleLimits(v, name, &argp, errp)) {
 894        return;
 895    }
 896    qemu_mutex_lock(&tg->lock);
 897    throttle_get_config(&tg->ts, &cfg);
 898    throttle_limits_to_config(argp, &cfg, &local_err);
 899    if (local_err) {
 900        goto unlock;
 901    }
 902    throttle_config(&tg->ts, tg->clock_type, &cfg);
 903
 904unlock:
 905    qemu_mutex_unlock(&tg->lock);
 906    qapi_free_ThrottleLimits(argp);
 907    error_propagate(errp, local_err);
 908    return;
 909}
 910
 911static void throttle_group_get_limits(Object *obj, Visitor *v,
 912                                      const char *name, void *opaque,
 913                                      Error **errp)
 914{
 915    ThrottleGroup *tg = THROTTLE_GROUP(obj);
 916    ThrottleConfig cfg;
 917    ThrottleLimits arg = { 0 };
 918    ThrottleLimits *argp = &arg;
 919
 920    qemu_mutex_lock(&tg->lock);
 921    throttle_get_config(&tg->ts, &cfg);
 922    qemu_mutex_unlock(&tg->lock);
 923
 924    throttle_config_to_limits(&cfg, argp);
 925
 926    visit_type_ThrottleLimits(v, name, &argp, errp);
 927}
 928
 929static bool throttle_group_can_be_deleted(UserCreatable *uc)
 930{
 931    return OBJECT(uc)->ref == 1;
 932}
 933
 934static void throttle_group_obj_class_init(ObjectClass *klass, void *class_data)
 935{
 936    size_t i = 0;
 937    UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
 938
 939    ucc->complete = throttle_group_obj_complete;
 940    ucc->can_be_deleted = throttle_group_can_be_deleted;
 941
 942    /* individual properties */
 943    for (i = 0; i < sizeof(properties) / sizeof(ThrottleParamInfo); i++) {
 944        object_class_property_add(klass,
 945                                  properties[i].name,
 946                                  "int",
 947                                  throttle_group_get,
 948                                  throttle_group_set,
 949                                  NULL, &properties[i]);
 950    }
 951
 952    /* ThrottleLimits */
 953    object_class_property_add(klass,
 954                              "limits", "ThrottleLimits",
 955                              throttle_group_get_limits,
 956                              throttle_group_set_limits,
 957                              NULL, NULL);
 958}
 959
 960static const TypeInfo throttle_group_info = {
 961    .name = TYPE_THROTTLE_GROUP,
 962    .parent = TYPE_OBJECT,
 963    .class_init = throttle_group_obj_class_init,
 964    .instance_size = sizeof(ThrottleGroup),
 965    .instance_init = throttle_group_obj_init,
 966    .instance_finalize = throttle_group_obj_finalize,
 967    .interfaces = (InterfaceInfo[]) {
 968        { TYPE_USER_CREATABLE },
 969        { }
 970    },
 971};
 972
 973static void throttle_groups_init(void)
 974{
 975    type_register_static(&throttle_group_info);
 976}
 977
 978type_init(throttle_groups_init);
 979