cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

test-throttle.c (23896B)


      1/*
      2 * Throttle infrastructure tests
      3 *
      4 * Copyright Nodalink, EURL. 2013-2014
      5 * Copyright Igalia, S.L. 2015
      6 *
      7 * Authors:
      8 *  BenoƮt Canet     <benoit.canet@nodalink.com>
      9 *  Alberto Garcia   <berto@igalia.com>
     10 *
     11 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
     12 * See the COPYING.LIB file in the top-level directory.
     13 */
     14
     15#include "qemu/osdep.h"
     16#include <math.h>
     17#include "block/aio.h"
     18#include "qapi/error.h"
     19#include "qemu/throttle.h"
     20#include "qemu/error-report.h"
     21#include "qemu/main-loop.h"
     22#include "qemu/module.h"
     23#include "block/throttle-groups.h"
     24#include "sysemu/block-backend.h"
     25
     26static AioContext     *ctx;
     27static LeakyBucket    bkt;
     28static ThrottleConfig cfg;
     29static ThrottleGroupMember tgm;
     30static ThrottleState  ts;
     31static ThrottleTimers *tt;
     32
     33/* useful function */
     34static bool double_cmp(double x, double y)
     35{
     36    return fabsl(x - y) < 1e-6;
     37}
     38
     39/* tests for single bucket operations */
     40static void test_leak_bucket(void)
     41{
     42    throttle_config_init(&cfg);
     43    bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
     44
     45    /* set initial value */
     46    bkt.avg = 150;
     47    bkt.max = 15;
     48    bkt.level = 1.5;
     49
     50    /* leak an op work of time */
     51    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
     52    g_assert(bkt.avg == 150);
     53    g_assert(bkt.max == 15);
     54    g_assert(double_cmp(bkt.level, 0.5));
     55
     56    /* leak again emptying the bucket */
     57    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
     58    g_assert(bkt.avg == 150);
     59    g_assert(bkt.max == 15);
     60    g_assert(double_cmp(bkt.level, 0));
     61
     62    /* check that the bucket level won't go lower */
     63    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150);
     64    g_assert(bkt.avg == 150);
     65    g_assert(bkt.max == 15);
     66    g_assert(double_cmp(bkt.level, 0));
     67
     68    /* check that burst_level leaks correctly */
     69    bkt.burst_level = 6;
     70    bkt.max = 250;
     71    bkt.burst_length = 2; /* otherwise burst_level will not leak */
     72    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
     73    g_assert(double_cmp(bkt.burst_level, 3.5));
     74
     75    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
     76    g_assert(double_cmp(bkt.burst_level, 1));
     77
     78    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
     79    g_assert(double_cmp(bkt.burst_level, 0));
     80
     81    throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
     82    g_assert(double_cmp(bkt.burst_level, 0));
     83}
     84
     85static void test_compute_wait(void)
     86{
     87    unsigned i;
     88    int64_t wait;
     89    int64_t result;
     90
     91    throttle_config_init(&cfg);
     92    bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
     93
     94    /* no operation limit set */
     95    bkt.avg = 0;
     96    bkt.max = 15;
     97    bkt.level = 1.5;
     98    wait = throttle_compute_wait(&bkt);
     99    g_assert(!wait);
    100
    101    /* zero delta */
    102    bkt.avg = 150;
    103    bkt.max = 15;
    104    bkt.level = 15;
    105    wait = throttle_compute_wait(&bkt);
    106    g_assert(!wait);
    107
    108    /* below zero delta */
    109    bkt.avg = 150;
    110    bkt.max = 15;
    111    bkt.level = 9;
    112    wait = throttle_compute_wait(&bkt);
    113    g_assert(!wait);
    114
    115    /* half an operation above max */
    116    bkt.avg = 150;
    117    bkt.max = 15;
    118    bkt.level = 15.5;
    119    wait = throttle_compute_wait(&bkt);
    120    /* time required to do half an operation */
    121    result = (int64_t)  NANOSECONDS_PER_SECOND / 150 / 2;
    122    g_assert(wait == result);
    123
    124    /* Perform I/O for 2.2 seconds at a rate of bkt.max */
    125    bkt.burst_length = 2;
    126    bkt.level = 0;
    127    bkt.avg = 10;
    128    bkt.max = 200;
    129    for (i = 0; i < 22; i++) {
    130        double units = bkt.max / 10;
    131        bkt.level += units;
    132        bkt.burst_level += units;
    133        throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 10);
    134        wait = throttle_compute_wait(&bkt);
    135        g_assert(double_cmp(bkt.burst_level, 0));
    136        g_assert(double_cmp(bkt.level, (i + 1) * (bkt.max - bkt.avg) / 10));
    137        /* We can do bursts for the 2 seconds we have configured in
    138         * burst_length. We have 100 extra miliseconds of burst
    139         * because bkt.level has been leaking during this time.
    140         * After that, we have to wait. */
    141        result = i < 21 ? 0 : 1.8 * NANOSECONDS_PER_SECOND;
    142        g_assert(wait == result);
    143    }
    144}
    145
    146/* functions to test ThrottleState initialization/destroy methods */
    147static void read_timer_cb(void *opaque)
    148{
    149}
    150
    151static void write_timer_cb(void *opaque)
    152{
    153}
    154
    155static void test_init(void)
    156{
    157    int i;
    158
    159    tt = &tgm.throttle_timers;
    160
    161    /* fill the structures with crap */
    162    memset(&ts, 1, sizeof(ts));
    163    memset(tt, 1, sizeof(*tt));
    164
    165    /* init structures */
    166    throttle_init(&ts);
    167    throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
    168                         read_timer_cb, write_timer_cb, &ts);
    169
    170    /* check initialized fields */
    171    g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL);
    172    g_assert(tt->timers[0]);
    173    g_assert(tt->timers[1]);
    174
    175    /* check other fields where cleared */
    176    g_assert(!ts.previous_leak);
    177    g_assert(!ts.cfg.op_size);
    178    for (i = 0; i < BUCKETS_COUNT; i++) {
    179        g_assert(!ts.cfg.buckets[i].avg);
    180        g_assert(!ts.cfg.buckets[i].max);
    181        g_assert(!ts.cfg.buckets[i].level);
    182    }
    183
    184    throttle_timers_destroy(tt);
    185}
    186
    187static void test_destroy(void)
    188{
    189    int i;
    190    throttle_init(&ts);
    191    throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
    192                         read_timer_cb, write_timer_cb, &ts);
    193    throttle_timers_destroy(tt);
    194    for (i = 0; i < 2; i++) {
    195        g_assert(!tt->timers[i]);
    196    }
    197}
    198
    199/* function to test throttle_config and throttle_get_config */
    200static void test_config_functions(void)
    201{
    202    int i;
    203    ThrottleConfig orig_cfg, final_cfg;
    204
    205    orig_cfg.buckets[THROTTLE_BPS_TOTAL].avg = 153;
    206    orig_cfg.buckets[THROTTLE_BPS_READ].avg  = 56;
    207    orig_cfg.buckets[THROTTLE_BPS_WRITE].avg = 1;
    208
    209    orig_cfg.buckets[THROTTLE_OPS_TOTAL].avg = 150;
    210    orig_cfg.buckets[THROTTLE_OPS_READ].avg  = 69;
    211    orig_cfg.buckets[THROTTLE_OPS_WRITE].avg = 23;
    212
    213    orig_cfg.buckets[THROTTLE_BPS_TOTAL].max = 0;
    214    orig_cfg.buckets[THROTTLE_BPS_READ].max  = 56;
    215    orig_cfg.buckets[THROTTLE_BPS_WRITE].max = 120;
    216
    217    orig_cfg.buckets[THROTTLE_OPS_TOTAL].max = 150;
    218    orig_cfg.buckets[THROTTLE_OPS_READ].max  = 400;
    219    orig_cfg.buckets[THROTTLE_OPS_WRITE].max = 500;
    220
    221    orig_cfg.buckets[THROTTLE_BPS_TOTAL].level = 45;
    222    orig_cfg.buckets[THROTTLE_BPS_READ].level  = 65;
    223    orig_cfg.buckets[THROTTLE_BPS_WRITE].level = 23;
    224
    225    orig_cfg.buckets[THROTTLE_OPS_TOTAL].level = 1;
    226    orig_cfg.buckets[THROTTLE_OPS_READ].level  = 90;
    227    orig_cfg.buckets[THROTTLE_OPS_WRITE].level = 75;
    228
    229    orig_cfg.op_size = 1;
    230
    231    throttle_init(&ts);
    232    throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
    233                         read_timer_cb, write_timer_cb, &ts);
    234    /* structure reset by throttle_init previous_leak should be null */
    235    g_assert(!ts.previous_leak);
    236    throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &orig_cfg);
    237
    238    /* has previous leak been initialized by throttle_config ? */
    239    g_assert(ts.previous_leak);
    240
    241    /* get back the fixed configuration */
    242    throttle_get_config(&ts, &final_cfg);
    243
    244    throttle_timers_destroy(tt);
    245
    246    g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].avg == 153);
    247    g_assert(final_cfg.buckets[THROTTLE_BPS_READ].avg  == 56);
    248    g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].avg == 1);
    249
    250    g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].avg == 150);
    251    g_assert(final_cfg.buckets[THROTTLE_OPS_READ].avg  == 69);
    252    g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].avg == 23);
    253
    254    g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].max == 0);
    255    g_assert(final_cfg.buckets[THROTTLE_BPS_READ].max  == 56);
    256    g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].max == 120);
    257
    258    g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].max == 150);
    259    g_assert(final_cfg.buckets[THROTTLE_OPS_READ].max  == 400);
    260    g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].max == 500);
    261
    262    g_assert(final_cfg.op_size == 1);
    263
    264    /* check bucket have been cleared */
    265    for (i = 0; i < BUCKETS_COUNT; i++) {
    266        g_assert(!final_cfg.buckets[i].level);
    267    }
    268}
    269
    270/* functions to test is throttle is enabled by a config */
    271static void set_cfg_value(bool is_max, int index, int value)
    272{
    273    if (is_max) {
    274        cfg.buckets[index].max = value;
    275        /* If max is set, avg should never be 0 */
    276        cfg.buckets[index].avg = MAX(cfg.buckets[index].avg, 1);
    277    } else {
    278        cfg.buckets[index].avg = value;
    279    }
    280}
    281
    282static void test_enabled(void)
    283{
    284    int i;
    285
    286    throttle_config_init(&cfg);
    287    g_assert(!throttle_enabled(&cfg));
    288
    289    for (i = 0; i < BUCKETS_COUNT; i++) {
    290        throttle_config_init(&cfg);
    291        set_cfg_value(false, i, 150);
    292        g_assert(throttle_is_valid(&cfg, NULL));
    293        g_assert(throttle_enabled(&cfg));
    294    }
    295
    296    for (i = 0; i < BUCKETS_COUNT; i++) {
    297        throttle_config_init(&cfg);
    298        set_cfg_value(false, i, -150);
    299        g_assert(!throttle_is_valid(&cfg, NULL));
    300    }
    301}
    302
    303/* tests functions for throttle_conflicting */
    304
    305static void test_conflicts_for_one_set(bool is_max,
    306                                       int total,
    307                                       int read,
    308                                       int write)
    309{
    310    throttle_config_init(&cfg);
    311    g_assert(throttle_is_valid(&cfg, NULL));
    312
    313    set_cfg_value(is_max, total, 1);
    314    set_cfg_value(is_max, read,  1);
    315    g_assert(!throttle_is_valid(&cfg, NULL));
    316
    317    throttle_config_init(&cfg);
    318    set_cfg_value(is_max, total, 1);
    319    set_cfg_value(is_max, write, 1);
    320    g_assert(!throttle_is_valid(&cfg, NULL));
    321
    322    throttle_config_init(&cfg);
    323    set_cfg_value(is_max, total, 1);
    324    set_cfg_value(is_max, read,  1);
    325    set_cfg_value(is_max, write, 1);
    326    g_assert(!throttle_is_valid(&cfg, NULL));
    327
    328    throttle_config_init(&cfg);
    329    set_cfg_value(is_max, total, 1);
    330    g_assert(throttle_is_valid(&cfg, NULL));
    331
    332    throttle_config_init(&cfg);
    333    set_cfg_value(is_max, read,  1);
    334    set_cfg_value(is_max, write, 1);
    335    g_assert(throttle_is_valid(&cfg, NULL));
    336}
    337
    338static void test_conflicting_config(void)
    339{
    340    /* bps average conflicts */
    341    test_conflicts_for_one_set(false,
    342                               THROTTLE_BPS_TOTAL,
    343                               THROTTLE_BPS_READ,
    344                               THROTTLE_BPS_WRITE);
    345
    346    /* ops average conflicts */
    347    test_conflicts_for_one_set(false,
    348                               THROTTLE_OPS_TOTAL,
    349                               THROTTLE_OPS_READ,
    350                               THROTTLE_OPS_WRITE);
    351
    352    /* bps average conflicts */
    353    test_conflicts_for_one_set(true,
    354                               THROTTLE_BPS_TOTAL,
    355                               THROTTLE_BPS_READ,
    356                               THROTTLE_BPS_WRITE);
    357    /* ops average conflicts */
    358    test_conflicts_for_one_set(true,
    359                               THROTTLE_OPS_TOTAL,
    360                               THROTTLE_OPS_READ,
    361                               THROTTLE_OPS_WRITE);
    362}
    363/* functions to test the throttle_is_valid function */
    364static void test_is_valid_for_value(int value, bool should_be_valid)
    365{
    366    int is_max, index;
    367    for (is_max = 0; is_max < 2; is_max++) {
    368        for (index = 0; index < BUCKETS_COUNT; index++) {
    369            throttle_config_init(&cfg);
    370            set_cfg_value(is_max, index, value);
    371            g_assert(throttle_is_valid(&cfg, NULL) == should_be_valid);
    372        }
    373    }
    374}
    375
    376static void test_is_valid(void)
    377{
    378    /* negative number are invalid */
    379    test_is_valid_for_value(-1, false);
    380    /* zero are valids */
    381    test_is_valid_for_value(0, true);
    382    /* positives numers are valids */
    383    test_is_valid_for_value(1, true);
    384}
    385
    386static void test_ranges(void)
    387{
    388    int i;
    389
    390    for (i = 0; i < BUCKETS_COUNT; i++) {
    391        LeakyBucket *b = &cfg.buckets[i];
    392        throttle_config_init(&cfg);
    393
    394        /* avg = 0 means throttling is disabled, but the config is valid */
    395        b->avg = 0;
    396        g_assert(throttle_is_valid(&cfg, NULL));
    397        g_assert(!throttle_enabled(&cfg));
    398
    399        /* These are valid configurations (values <= THROTTLE_VALUE_MAX) */
    400        b->avg = 1;
    401        g_assert(throttle_is_valid(&cfg, NULL));
    402
    403        b->avg = THROTTLE_VALUE_MAX;
    404        g_assert(throttle_is_valid(&cfg, NULL));
    405
    406        b->avg = THROTTLE_VALUE_MAX;
    407        b->max = THROTTLE_VALUE_MAX;
    408        g_assert(throttle_is_valid(&cfg, NULL));
    409
    410        /* Values over THROTTLE_VALUE_MAX are not allowed */
    411        b->avg = THROTTLE_VALUE_MAX + 1;
    412        g_assert(!throttle_is_valid(&cfg, NULL));
    413
    414        b->avg = THROTTLE_VALUE_MAX;
    415        b->max = THROTTLE_VALUE_MAX + 1;
    416        g_assert(!throttle_is_valid(&cfg, NULL));
    417
    418        /* burst_length must be between 1 and THROTTLE_VALUE_MAX */
    419        b->avg = 1;
    420        b->max = 1;
    421        b->burst_length = 0;
    422        g_assert(!throttle_is_valid(&cfg, NULL));
    423
    424        b->avg = 1;
    425        b->max = 1;
    426        b->burst_length = 1;
    427        g_assert(throttle_is_valid(&cfg, NULL));
    428
    429        b->avg = 1;
    430        b->max = 1;
    431        b->burst_length = THROTTLE_VALUE_MAX;
    432        g_assert(throttle_is_valid(&cfg, NULL));
    433
    434        b->avg = 1;
    435        b->max = 1;
    436        b->burst_length = THROTTLE_VALUE_MAX + 1;
    437        g_assert(!throttle_is_valid(&cfg, NULL));
    438
    439        /* burst_length * max cannot exceed THROTTLE_VALUE_MAX */
    440        b->avg = 1;
    441        b->max = 2;
    442        b->burst_length = THROTTLE_VALUE_MAX / 2;
    443        g_assert(throttle_is_valid(&cfg, NULL));
    444
    445        b->avg = 1;
    446        b->max = 3;
    447        b->burst_length = THROTTLE_VALUE_MAX / 2;
    448        g_assert(!throttle_is_valid(&cfg, NULL));
    449
    450        b->avg = 1;
    451        b->max = THROTTLE_VALUE_MAX;
    452        b->burst_length = 1;
    453        g_assert(throttle_is_valid(&cfg, NULL));
    454
    455        b->avg = 1;
    456        b->max = THROTTLE_VALUE_MAX;
    457        b->burst_length = 2;
    458        g_assert(!throttle_is_valid(&cfg, NULL));
    459    }
    460}
    461
    462static void test_max_is_missing_limit(void)
    463{
    464    int i;
    465
    466    for (i = 0; i < BUCKETS_COUNT; i++) {
    467        throttle_config_init(&cfg);
    468        cfg.buckets[i].max = 100;
    469        cfg.buckets[i].avg = 0;
    470        g_assert(!throttle_is_valid(&cfg, NULL));
    471
    472        cfg.buckets[i].max = 0;
    473        cfg.buckets[i].avg = 0;
    474        g_assert(throttle_is_valid(&cfg, NULL));
    475
    476        cfg.buckets[i].max = 0;
    477        cfg.buckets[i].avg = 100;
    478        g_assert(throttle_is_valid(&cfg, NULL));
    479
    480        cfg.buckets[i].max = 30;
    481        cfg.buckets[i].avg = 100;
    482        g_assert(!throttle_is_valid(&cfg, NULL));
    483
    484        cfg.buckets[i].max = 100;
    485        cfg.buckets[i].avg = 100;
    486        g_assert(throttle_is_valid(&cfg, NULL));
    487    }
    488}
    489
    490static void test_iops_size_is_missing_limit(void)
    491{
    492    /* A total/read/write iops limit is required */
    493    throttle_config_init(&cfg);
    494    cfg.op_size = 4096;
    495    g_assert(!throttle_is_valid(&cfg, NULL));
    496}
    497
    498static void test_have_timer(void)
    499{
    500    /* zero structures */
    501    memset(&ts, 0, sizeof(ts));
    502    memset(tt, 0, sizeof(*tt));
    503
    504    /* no timer set should return false */
    505    g_assert(!throttle_timers_are_initialized(tt));
    506
    507    /* init structures */
    508    throttle_init(&ts);
    509    throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
    510                         read_timer_cb, write_timer_cb, &ts);
    511
    512    /* timer set by init should return true */
    513    g_assert(throttle_timers_are_initialized(tt));
    514
    515    throttle_timers_destroy(tt);
    516}
    517
    518static void test_detach_attach(void)
    519{
    520    /* zero structures */
    521    memset(&ts, 0, sizeof(ts));
    522    memset(tt, 0, sizeof(*tt));
    523
    524    /* init the structure */
    525    throttle_init(&ts);
    526    throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
    527                         read_timer_cb, write_timer_cb, &ts);
    528
    529    /* timer set by init should return true */
    530    g_assert(throttle_timers_are_initialized(tt));
    531
    532    /* timer should no longer exist after detaching */
    533    throttle_timers_detach_aio_context(tt);
    534    g_assert(!throttle_timers_are_initialized(tt));
    535
    536    /* timer should exist again after attaching */
    537    throttle_timers_attach_aio_context(tt, ctx);
    538    g_assert(throttle_timers_are_initialized(tt));
    539
    540    throttle_timers_destroy(tt);
    541}
    542
    543static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
    544                int size,                   /* size of the operation to do */
    545                double avg,                 /* io limit */
    546                uint64_t op_size,           /* ideal size of an io */
    547                double total_result,
    548                double read_result,
    549                double write_result)
    550{
    551    BucketType to_test[2][3] = { { THROTTLE_BPS_TOTAL,
    552                                   THROTTLE_BPS_READ,
    553                                   THROTTLE_BPS_WRITE, },
    554                                 { THROTTLE_OPS_TOTAL,
    555                                   THROTTLE_OPS_READ,
    556                                   THROTTLE_OPS_WRITE, } };
    557    ThrottleConfig cfg;
    558    BucketType index;
    559    int i;
    560
    561    throttle_config_init(&cfg);
    562
    563    for (i = 0; i < 3; i++) {
    564        BucketType index = to_test[is_ops][i];
    565        cfg.buckets[index].avg = avg;
    566    }
    567
    568    cfg.op_size = op_size;
    569
    570    throttle_init(&ts);
    571    throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL,
    572                         read_timer_cb, write_timer_cb, &ts);
    573    throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &cfg);
    574
    575    /* account a read */
    576    throttle_account(&ts, false, size);
    577    /* account a write */
    578    throttle_account(&ts, true, size);
    579
    580    /* check total result */
    581    index = to_test[is_ops][0];
    582    if (!double_cmp(ts.cfg.buckets[index].level, total_result)) {
    583        return false;
    584    }
    585
    586    /* check read result */
    587    index = to_test[is_ops][1];
    588    if (!double_cmp(ts.cfg.buckets[index].level, read_result)) {
    589        return false;
    590    }
    591
    592    /* check write result */
    593    index = to_test[is_ops][2];
    594    if (!double_cmp(ts.cfg.buckets[index].level, write_result)) {
    595        return false;
    596    }
    597
    598    throttle_timers_destroy(tt);
    599
    600    return true;
    601}
    602
    603static void test_accounting(void)
    604{
    605    /* tests for bps */
    606
    607    /* op of size 1 */
    608    g_assert(do_test_accounting(false,
    609                                1 * 512,
    610                                150,
    611                                0,
    612                                1024,
    613                                512,
    614                                512));
    615
    616    /* op of size 2 */
    617    g_assert(do_test_accounting(false,
    618                                2 * 512,
    619                                150,
    620                                0,
    621                                2048,
    622                                1024,
    623                                1024));
    624
    625    /* op of size 2 and orthogonal parameter change */
    626    g_assert(do_test_accounting(false,
    627                                2 * 512,
    628                                150,
    629                                17,
    630                                2048,
    631                                1024,
    632                                1024));
    633
    634
    635    /* tests for ops */
    636
    637    /* op of size 1 */
    638    g_assert(do_test_accounting(true,
    639                                1 * 512,
    640                                150,
    641                                0,
    642                                2,
    643                                1,
    644                                1));
    645
    646    /* op of size 2 */
    647    g_assert(do_test_accounting(true,
    648                                2 *  512,
    649                                150,
    650                                0,
    651                                2,
    652                                1,
    653                                1));
    654
    655    /* jumbo op accounting fragmentation : size 64 with op size of 13 units */
    656    g_assert(do_test_accounting(true,
    657                                64 * 512,
    658                                150,
    659                                13 * 512,
    660                                (64.0 * 2) / 13,
    661                                (64.0 / 13),
    662                                (64.0 / 13)));
    663
    664    /* same with orthogonal parameters changes */
    665    g_assert(do_test_accounting(true,
    666                                64 * 512,
    667                                300,
    668                                13 * 512,
    669                                (64.0 * 2) / 13,
    670                                (64.0 / 13),
    671                                (64.0 / 13)));
    672}
    673
    674static void test_groups(void)
    675{
    676    ThrottleConfig cfg1, cfg2;
    677    BlockBackend *blk1, *blk2, *blk3;
    678    BlockBackendPublic *blkp1, *blkp2, *blkp3;
    679    ThrottleGroupMember *tgm1, *tgm2, *tgm3;
    680
    681    /* No actual I/O is performed on these devices */
    682    blk1 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
    683    blk2 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
    684    blk3 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
    685
    686    blkp1 = blk_get_public(blk1);
    687    blkp2 = blk_get_public(blk2);
    688    blkp3 = blk_get_public(blk3);
    689
    690    tgm1 = &blkp1->throttle_group_member;
    691    tgm2 = &blkp2->throttle_group_member;
    692    tgm3 = &blkp3->throttle_group_member;
    693
    694    g_assert(tgm1->throttle_state == NULL);
    695    g_assert(tgm2->throttle_state == NULL);
    696    g_assert(tgm3->throttle_state == NULL);
    697
    698    throttle_group_register_tgm(tgm1, "bar", blk_get_aio_context(blk1));
    699    throttle_group_register_tgm(tgm2, "foo", blk_get_aio_context(blk2));
    700    throttle_group_register_tgm(tgm3, "bar", blk_get_aio_context(blk3));
    701
    702    g_assert(tgm1->throttle_state != NULL);
    703    g_assert(tgm2->throttle_state != NULL);
    704    g_assert(tgm3->throttle_state != NULL);
    705
    706    g_assert(!strcmp(throttle_group_get_name(tgm1), "bar"));
    707    g_assert(!strcmp(throttle_group_get_name(tgm2), "foo"));
    708    g_assert(tgm1->throttle_state == tgm3->throttle_state);
    709
    710    /* Setting the config of a group member affects the whole group */
    711    throttle_config_init(&cfg1);
    712    cfg1.buckets[THROTTLE_BPS_READ].avg  = 500000;
    713    cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000;
    714    cfg1.buckets[THROTTLE_OPS_READ].avg  = 20000;
    715    cfg1.buckets[THROTTLE_OPS_WRITE].avg = 12000;
    716    throttle_group_config(tgm1, &cfg1);
    717
    718    throttle_group_get_config(tgm1, &cfg1);
    719    throttle_group_get_config(tgm3, &cfg2);
    720    g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
    721
    722    cfg2.buckets[THROTTLE_BPS_READ].avg  = 4547;
    723    cfg2.buckets[THROTTLE_BPS_WRITE].avg = 1349;
    724    cfg2.buckets[THROTTLE_OPS_READ].avg  = 123;
    725    cfg2.buckets[THROTTLE_OPS_WRITE].avg = 86;
    726    throttle_group_config(tgm3, &cfg1);
    727
    728    throttle_group_get_config(tgm1, &cfg1);
    729    throttle_group_get_config(tgm3, &cfg2);
    730    g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1)));
    731
    732    throttle_group_unregister_tgm(tgm1);
    733    throttle_group_unregister_tgm(tgm2);
    734    throttle_group_unregister_tgm(tgm3);
    735
    736    g_assert(tgm1->throttle_state == NULL);
    737    g_assert(tgm2->throttle_state == NULL);
    738    g_assert(tgm3->throttle_state == NULL);
    739}
    740
    741int main(int argc, char **argv)
    742{
    743    qemu_init_main_loop(&error_fatal);
    744    ctx = qemu_get_aio_context();
    745    bdrv_init();
    746    module_call_init(MODULE_INIT_QOM);
    747
    748    do {} while (g_main_context_iteration(NULL, false));
    749
    750    /* tests in the same order as the header function declarations */
    751    g_test_init(&argc, &argv, NULL);
    752    g_test_add_func("/throttle/leak_bucket",        test_leak_bucket);
    753    g_test_add_func("/throttle/compute_wait",       test_compute_wait);
    754    g_test_add_func("/throttle/init",               test_init);
    755    g_test_add_func("/throttle/destroy",            test_destroy);
    756    g_test_add_func("/throttle/have_timer",         test_have_timer);
    757    g_test_add_func("/throttle/detach_attach",      test_detach_attach);
    758    g_test_add_func("/throttle/config/enabled",     test_enabled);
    759    g_test_add_func("/throttle/config/conflicting", test_conflicting_config);
    760    g_test_add_func("/throttle/config/is_valid",    test_is_valid);
    761    g_test_add_func("/throttle/config/ranges",      test_ranges);
    762    g_test_add_func("/throttle/config/max",         test_max_is_missing_limit);
    763    g_test_add_func("/throttle/config/iops_size",
    764                    test_iops_size_is_missing_limit);
    765    g_test_add_func("/throttle/config_functions",   test_config_functions);
    766    g_test_add_func("/throttle/accounting",         test_accounting);
    767    g_test_add_func("/throttle/groups",             test_groups);
    768    return g_test_run();
    769}
    770