qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

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 
     26 static AioContext     *ctx;
     27 static LeakyBucket    bkt;
     28 static ThrottleConfig cfg;
     29 static ThrottleGroupMember tgm;
     30 static ThrottleState  ts;
     31 static ThrottleTimers *tt;
     32 
     33 /* useful function */
     34 static bool double_cmp(double x, double y)
     35 {
     36     return fabsl(x - y) < 1e-6;
     37 }
     38 
     39 /* tests for single bucket operations */
     40 static 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 
     85 static 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 */
    147 static void read_timer_cb(void *opaque)
    148 {
    149 }
    150 
    151 static void write_timer_cb(void *opaque)
    152 {
    153 }
    154 
    155 static 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 
    187 static 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 */
    200 static 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 */
    271 static 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 
    282 static 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 
    305 static 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 
    338 static 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 */
    364 static 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 
    376 static 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 
    386 static 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 
    462 static 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 
    490 static 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 
    498 static 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 
    518 static 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 
    543 static 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 
    603 static 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 
    674 static 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 
    741 int 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