1f17cfe81SBenoît Canet /* 2f17cfe81SBenoît Canet * Throttle infrastructure tests 3f17cfe81SBenoît Canet * 41fee955fSAlberto Garcia * Copyright Nodalink, EURL. 2013-2014 51fee955fSAlberto Garcia * Copyright Igalia, S.L. 2015 6f17cfe81SBenoît Canet * 7f17cfe81SBenoît Canet * Authors: 81fee955fSAlberto Garcia * Benoît Canet <benoit.canet@nodalink.com> 91fee955fSAlberto Garcia * Alberto Garcia <berto@igalia.com> 10f17cfe81SBenoît Canet * 11f17cfe81SBenoît Canet * This work is licensed under the terms of the GNU LGPL, version 2 or later. 12f17cfe81SBenoît Canet * See the COPYING.LIB file in the top-level directory. 13f17cfe81SBenoît Canet */ 14f17cfe81SBenoît Canet 15681c28a3SPeter Maydell #include "qemu/osdep.h" 16f17cfe81SBenoît Canet #include <math.h> 1713af91ebSStefan Hajnoczi #include "block/aio.h" 18da34e65cSMarkus Armbruster #include "qapi/error.h" 19f17cfe81SBenoît Canet #include "qemu/throttle.h" 202f78e491SChrysostomos Nanakos #include "qemu/error-report.h" 21db725815SMarkus Armbruster #include "qemu/main-loop.h" 220b8fa32fSMarkus Armbruster #include "qemu/module.h" 231fee955fSAlberto Garcia #include "block/throttle-groups.h" 2431dce3ccSKevin Wolf #include "sysemu/block-backend.h" 25f17cfe81SBenoît Canet 26748bfb4eSStefan Weil static AioContext *ctx; 27748bfb4eSStefan Weil static LeakyBucket bkt; 28748bfb4eSStefan Weil static ThrottleConfig cfg; 29c61791fcSManos Pitsidianakis static ThrottleGroupMember tgm; 30748bfb4eSStefan Weil static ThrottleState ts; 31c61791fcSManos Pitsidianakis static ThrottleTimers *tt; 32f17cfe81SBenoît Canet 3373f395faSStefan Weil /* useful function */ 34f17cfe81SBenoît Canet static bool double_cmp(double x, double y) 35f17cfe81SBenoît Canet { 36f17cfe81SBenoît Canet return fabsl(x - y) < 1e-6; 37f17cfe81SBenoît Canet } 38f17cfe81SBenoît Canet 39f17cfe81SBenoît Canet /* tests for single bucket operations */ 40f17cfe81SBenoît Canet static void test_leak_bucket(void) 41f17cfe81SBenoît Canet { 421588ab5dSAlberto Garcia throttle_config_init(&cfg); 431588ab5dSAlberto Garcia bkt = cfg.buckets[THROTTLE_BPS_TOTAL]; 441588ab5dSAlberto Garcia 45f17cfe81SBenoît Canet /* set initial value */ 46f17cfe81SBenoît Canet bkt.avg = 150; 47f17cfe81SBenoît Canet bkt.max = 15; 48f17cfe81SBenoît Canet bkt.level = 1.5; 49f17cfe81SBenoît Canet 50f17cfe81SBenoît Canet /* leak an op work of time */ 5113566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150); 52f17cfe81SBenoît Canet g_assert(bkt.avg == 150); 53f17cfe81SBenoît Canet g_assert(bkt.max == 15); 54f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0.5)); 55f17cfe81SBenoît Canet 56f17cfe81SBenoît Canet /* leak again emptying the bucket */ 5713566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150); 58f17cfe81SBenoît Canet g_assert(bkt.avg == 150); 59f17cfe81SBenoît Canet g_assert(bkt.max == 15); 60f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0)); 61f17cfe81SBenoît Canet 62f17cfe81SBenoît Canet /* check that the bucket level won't go lower */ 6313566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150); 64f17cfe81SBenoît Canet g_assert(bkt.avg == 150); 65f17cfe81SBenoît Canet g_assert(bkt.max == 15); 66f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0)); 67eb8a1a1cSAlberto Garcia 68eb8a1a1cSAlberto Garcia /* check that burst_level leaks correctly */ 69eb8a1a1cSAlberto Garcia bkt.burst_level = 6; 70eb8a1a1cSAlberto Garcia bkt.max = 250; 71eb8a1a1cSAlberto Garcia bkt.burst_length = 2; /* otherwise burst_level will not leak */ 72eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100); 73eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 3.5)); 74eb8a1a1cSAlberto Garcia 75eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100); 76eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 1)); 77eb8a1a1cSAlberto Garcia 78eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100); 79eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 0)); 80eb8a1a1cSAlberto Garcia 81eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100); 82eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 0)); 83f17cfe81SBenoît Canet } 84f17cfe81SBenoît Canet 85f17cfe81SBenoît Canet static void test_compute_wait(void) 86f17cfe81SBenoît Canet { 87f9d05885SAlberto Garcia unsigned i; 88f17cfe81SBenoît Canet int64_t wait; 89f17cfe81SBenoît Canet int64_t result; 90f17cfe81SBenoît Canet 911588ab5dSAlberto Garcia throttle_config_init(&cfg); 921588ab5dSAlberto Garcia bkt = cfg.buckets[THROTTLE_BPS_TOTAL]; 931588ab5dSAlberto Garcia 94f17cfe81SBenoît Canet /* no operation limit set */ 95f17cfe81SBenoît Canet bkt.avg = 0; 96f17cfe81SBenoît Canet bkt.max = 15; 97f17cfe81SBenoît Canet bkt.level = 1.5; 98f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 99f17cfe81SBenoît Canet g_assert(!wait); 100f17cfe81SBenoît Canet 101f17cfe81SBenoît Canet /* zero delta */ 102f17cfe81SBenoît Canet bkt.avg = 150; 103f17cfe81SBenoît Canet bkt.max = 15; 104f17cfe81SBenoît Canet bkt.level = 15; 105f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 106f17cfe81SBenoît Canet g_assert(!wait); 107f17cfe81SBenoît Canet 108f17cfe81SBenoît Canet /* below zero delta */ 109f17cfe81SBenoît Canet bkt.avg = 150; 110f17cfe81SBenoît Canet bkt.max = 15; 111f17cfe81SBenoît Canet bkt.level = 9; 112f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 113f17cfe81SBenoît Canet g_assert(!wait); 114f17cfe81SBenoît Canet 115f17cfe81SBenoît Canet /* half an operation above max */ 116f17cfe81SBenoît Canet bkt.avg = 150; 117f17cfe81SBenoît Canet bkt.max = 15; 118f17cfe81SBenoît Canet bkt.level = 15.5; 119f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 120f17cfe81SBenoît Canet /* time required to do half an operation */ 12113566fe3SStefan Hajnoczi result = (int64_t) NANOSECONDS_PER_SECOND / 150 / 2; 122f17cfe81SBenoît Canet g_assert(wait == result); 123f9d05885SAlberto Garcia 124f9d05885SAlberto Garcia /* Perform I/O for 2.2 seconds at a rate of bkt.max */ 125f9d05885SAlberto Garcia bkt.burst_length = 2; 126f9d05885SAlberto Garcia bkt.level = 0; 127f9d05885SAlberto Garcia bkt.avg = 10; 128f9d05885SAlberto Garcia bkt.max = 200; 129f9d05885SAlberto Garcia for (i = 0; i < 22; i++) { 130*43199b13SPeter Maydell double units = bkt.max / 10.0; 131f9d05885SAlberto Garcia bkt.level += units; 132f9d05885SAlberto Garcia bkt.burst_level += units; 133f9d05885SAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 10); 134f9d05885SAlberto Garcia wait = throttle_compute_wait(&bkt); 135f9d05885SAlberto Garcia g_assert(double_cmp(bkt.burst_level, 0)); 136*43199b13SPeter Maydell g_assert(double_cmp(bkt.level, (i + 1) * (bkt.max - bkt.avg) / 10.0)); 137f9d05885SAlberto Garcia /* We can do bursts for the 2 seconds we have configured in 13896420a30SMichael Tokarev * burst_length. We have 100 extra milliseconds of burst 139f9d05885SAlberto Garcia * because bkt.level has been leaking during this time. 140f9d05885SAlberto Garcia * After that, we have to wait. */ 141f9d05885SAlberto Garcia result = i < 21 ? 0 : 1.8 * NANOSECONDS_PER_SECOND; 142f9d05885SAlberto Garcia g_assert(wait == result); 143f9d05885SAlberto Garcia } 144f17cfe81SBenoît Canet } 145f17cfe81SBenoît Canet 146f17cfe81SBenoît Canet /* functions to test ThrottleState initialization/destroy methods */ 147f17cfe81SBenoît Canet static void read_timer_cb(void *opaque) 148f17cfe81SBenoît Canet { 149f17cfe81SBenoît Canet } 150f17cfe81SBenoît Canet 151f17cfe81SBenoît Canet static void write_timer_cb(void *opaque) 152f17cfe81SBenoît Canet { 153f17cfe81SBenoît Canet } 154f17cfe81SBenoît Canet 155f17cfe81SBenoît Canet static void test_init(void) 156f17cfe81SBenoît Canet { 157f17cfe81SBenoît Canet int i; 158f17cfe81SBenoît Canet 159c61791fcSManos Pitsidianakis tt = &tgm.throttle_timers; 160c61791fcSManos Pitsidianakis 1610e5b0a2dSBenoît Canet /* fill the structures with crap */ 162f17cfe81SBenoît Canet memset(&ts, 1, sizeof(ts)); 163c61791fcSManos Pitsidianakis memset(tt, 1, sizeof(*tt)); 164f17cfe81SBenoît Canet 1650e5b0a2dSBenoît Canet /* init structures */ 1660e5b0a2dSBenoît Canet throttle_init(&ts); 167c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL, 16813af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 169f17cfe81SBenoît Canet 170f17cfe81SBenoît Canet /* check initialized fields */ 171c61791fcSManos Pitsidianakis g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL); 1721322f63dSzhenwei pi g_assert(tt->timers[THROTTLE_READ]); 1731322f63dSzhenwei pi g_assert(tt->timers[THROTTLE_WRITE]); 174f17cfe81SBenoît Canet 175f17cfe81SBenoît Canet /* check other fields where cleared */ 176f17cfe81SBenoît Canet g_assert(!ts.previous_leak); 177f17cfe81SBenoît Canet g_assert(!ts.cfg.op_size); 178f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 179f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].avg); 180f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].max); 181f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].level); 182f17cfe81SBenoît Canet } 183f17cfe81SBenoît Canet 184c61791fcSManos Pitsidianakis throttle_timers_destroy(tt); 185f17cfe81SBenoît Canet } 186f17cfe81SBenoît Canet 18702add531Szhenwei pi static void test_init_readonly(void) 18802add531Szhenwei pi { 18902add531Szhenwei pi int i; 19002add531Szhenwei pi 19102add531Szhenwei pi tt = &tgm.throttle_timers; 19202add531Szhenwei pi 19302add531Szhenwei pi /* fill the structures with crap */ 19402add531Szhenwei pi memset(&ts, 1, sizeof(ts)); 19502add531Szhenwei pi memset(tt, 1, sizeof(*tt)); 19602add531Szhenwei pi 19702add531Szhenwei pi /* init structures */ 19802add531Szhenwei pi throttle_init(&ts); 19902add531Szhenwei pi throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL, 20002add531Szhenwei pi read_timer_cb, NULL, &ts); 20102add531Szhenwei pi 20202add531Szhenwei pi /* check initialized fields */ 20302add531Szhenwei pi g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL); 20402add531Szhenwei pi g_assert(tt->timers[THROTTLE_READ]); 20502add531Szhenwei pi g_assert(!tt->timers[THROTTLE_WRITE]); 20602add531Szhenwei pi 20702add531Szhenwei pi /* check other fields where cleared */ 20802add531Szhenwei pi g_assert(!ts.previous_leak); 20902add531Szhenwei pi g_assert(!ts.cfg.op_size); 21002add531Szhenwei pi for (i = 0; i < BUCKETS_COUNT; i++) { 21102add531Szhenwei pi g_assert(!ts.cfg.buckets[i].avg); 21202add531Szhenwei pi g_assert(!ts.cfg.buckets[i].max); 21302add531Szhenwei pi g_assert(!ts.cfg.buckets[i].level); 21402add531Szhenwei pi } 21502add531Szhenwei pi 21602add531Szhenwei pi throttle_timers_destroy(tt); 21702add531Szhenwei pi } 21802add531Szhenwei pi 21902add531Szhenwei pi static void test_init_writeonly(void) 22002add531Szhenwei pi { 22102add531Szhenwei pi int i; 22202add531Szhenwei pi 22302add531Szhenwei pi tt = &tgm.throttle_timers; 22402add531Szhenwei pi 22502add531Szhenwei pi /* fill the structures with crap */ 22602add531Szhenwei pi memset(&ts, 1, sizeof(ts)); 22702add531Szhenwei pi memset(tt, 1, sizeof(*tt)); 22802add531Szhenwei pi 22902add531Szhenwei pi /* init structures */ 23002add531Szhenwei pi throttle_init(&ts); 23102add531Szhenwei pi throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL, 23202add531Szhenwei pi NULL, write_timer_cb, &ts); 23302add531Szhenwei pi 23402add531Szhenwei pi /* check initialized fields */ 23502add531Szhenwei pi g_assert(tt->clock_type == QEMU_CLOCK_VIRTUAL); 23602add531Szhenwei pi g_assert(!tt->timers[THROTTLE_READ]); 23702add531Szhenwei pi g_assert(tt->timers[THROTTLE_WRITE]); 238f17cfe81SBenoît Canet 239f17cfe81SBenoît Canet /* check other fields where cleared */ 240f17cfe81SBenoît Canet g_assert(!ts.previous_leak); 241f17cfe81SBenoît Canet g_assert(!ts.cfg.op_size); 242f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 243f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].avg); 244f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].max); 245f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].level); 246f17cfe81SBenoît Canet } 247f17cfe81SBenoît Canet 248f17cfe81SBenoît Canet throttle_timers_destroy(tt); 249f17cfe81SBenoît Canet } 250f17cfe81SBenoît Canet 251f17cfe81SBenoît Canet static void test_destroy(void) 252f17cfe81SBenoît Canet { 253f17cfe81SBenoît Canet int i; 2540e5b0a2dSBenoît Canet throttle_init(&ts); 255c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL, 25613af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 257c61791fcSManos Pitsidianakis throttle_timers_destroy(tt); 2581322f63dSzhenwei pi for (i = 0; i < THROTTLE_MAX; i++) { 259c61791fcSManos Pitsidianakis g_assert(!tt->timers[i]); 260f17cfe81SBenoît Canet } 261f17cfe81SBenoît Canet } 262f17cfe81SBenoît Canet 263f17cfe81SBenoît Canet /* function to test throttle_config and throttle_get_config */ 264f17cfe81SBenoît Canet static void test_config_functions(void) 265f17cfe81SBenoît Canet { 266f17cfe81SBenoît Canet int i; 267f17cfe81SBenoît Canet ThrottleConfig orig_cfg, final_cfg; 268f17cfe81SBenoît Canet 269f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_TOTAL].avg = 153; 270f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_READ].avg = 56; 271f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].avg = 1; 272f17cfe81SBenoît Canet 273f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].avg = 150; 274f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].avg = 69; 275f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].avg = 23; 276f17cfe81SBenoît Canet 277d72915c6SStefan Hajnoczi orig_cfg.buckets[THROTTLE_BPS_TOTAL].max = 0; 278d72915c6SStefan Hajnoczi orig_cfg.buckets[THROTTLE_BPS_READ].max = 56; 279f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].max = 120; 280f17cfe81SBenoît Canet 281f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].max = 150; 282f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].max = 400; 283f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].max = 500; 284f17cfe81SBenoît Canet 285f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_TOTAL].level = 45; 286f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_READ].level = 65; 287f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].level = 23; 288f17cfe81SBenoît Canet 289f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].level = 1; 290f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].level = 90; 291f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].level = 75; 292f17cfe81SBenoît Canet 293f17cfe81SBenoît Canet orig_cfg.op_size = 1; 294f17cfe81SBenoît Canet 2950e5b0a2dSBenoît Canet throttle_init(&ts); 296c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL, 29713af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 298f17cfe81SBenoît Canet /* structure reset by throttle_init previous_leak should be null */ 299f17cfe81SBenoît Canet g_assert(!ts.previous_leak); 30027e4cf13SManos Pitsidianakis throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &orig_cfg); 301f17cfe81SBenoît Canet 302f17cfe81SBenoît Canet /* has previous leak been initialized by throttle_config ? */ 303f17cfe81SBenoît Canet g_assert(ts.previous_leak); 304f17cfe81SBenoît Canet 305f17cfe81SBenoît Canet /* get back the fixed configuration */ 306f17cfe81SBenoît Canet throttle_get_config(&ts, &final_cfg); 307f17cfe81SBenoît Canet 308c61791fcSManos Pitsidianakis throttle_timers_destroy(tt); 309f17cfe81SBenoît Canet 310f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].avg == 153); 311f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_READ].avg == 56); 312f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].avg == 1); 313f17cfe81SBenoît Canet 314f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].avg == 150); 315f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_READ].avg == 69); 316f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].avg == 23); 317f17cfe81SBenoît Canet 318d72915c6SStefan Hajnoczi g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].max == 0); 319d72915c6SStefan Hajnoczi g_assert(final_cfg.buckets[THROTTLE_BPS_READ].max == 56); 320f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].max == 120); 321f17cfe81SBenoît Canet 322f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].max == 150); 323f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_READ].max == 400); 324f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].max == 500); 325f17cfe81SBenoît Canet 326f17cfe81SBenoît Canet g_assert(final_cfg.op_size == 1); 327f17cfe81SBenoît Canet 328f17cfe81SBenoît Canet /* check bucket have been cleared */ 329f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 330f17cfe81SBenoît Canet g_assert(!final_cfg.buckets[i].level); 331f17cfe81SBenoît Canet } 332f17cfe81SBenoît Canet } 333f17cfe81SBenoît Canet 334f17cfe81SBenoît Canet /* functions to test is throttle is enabled by a config */ 335f17cfe81SBenoît Canet static void set_cfg_value(bool is_max, int index, int value) 336f17cfe81SBenoît Canet { 337f17cfe81SBenoît Canet if (is_max) { 338f17cfe81SBenoît Canet cfg.buckets[index].max = value; 3396f9b6d57SAlberto Garcia /* If max is set, avg should never be 0 */ 3406f9b6d57SAlberto Garcia cfg.buckets[index].avg = MAX(cfg.buckets[index].avg, 1); 341f17cfe81SBenoît Canet } else { 342f17cfe81SBenoît Canet cfg.buckets[index].avg = value; 343f17cfe81SBenoît Canet } 344f17cfe81SBenoît Canet } 345f17cfe81SBenoît Canet 346f17cfe81SBenoît Canet static void test_enabled(void) 347f17cfe81SBenoît Canet { 348f17cfe81SBenoît Canet int i; 349f17cfe81SBenoît Canet 3501588ab5dSAlberto Garcia throttle_config_init(&cfg); 351f17cfe81SBenoît Canet g_assert(!throttle_enabled(&cfg)); 352f17cfe81SBenoît Canet 353f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 3541588ab5dSAlberto Garcia throttle_config_init(&cfg); 355f17cfe81SBenoît Canet set_cfg_value(false, i, 150); 356d00e6923SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 357f17cfe81SBenoît Canet g_assert(throttle_enabled(&cfg)); 358f17cfe81SBenoît Canet } 359f17cfe81SBenoît Canet 360f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 3611588ab5dSAlberto Garcia throttle_config_init(&cfg); 362f17cfe81SBenoît Canet set_cfg_value(false, i, -150); 363d00e6923SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 364f17cfe81SBenoît Canet } 365f17cfe81SBenoît Canet } 366f17cfe81SBenoît Canet 367f17cfe81SBenoît Canet /* tests functions for throttle_conflicting */ 368f17cfe81SBenoît Canet 369f17cfe81SBenoît Canet static void test_conflicts_for_one_set(bool is_max, 370f17cfe81SBenoît Canet int total, 371f17cfe81SBenoît Canet int read, 372f17cfe81SBenoît Canet int write) 373f17cfe81SBenoît Canet { 3741588ab5dSAlberto Garcia throttle_config_init(&cfg); 375d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 376f17cfe81SBenoît Canet 377f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 378f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1); 379d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 380f17cfe81SBenoît Canet 3811588ab5dSAlberto Garcia throttle_config_init(&cfg); 382f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 383f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1); 384d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 385f17cfe81SBenoît Canet 3861588ab5dSAlberto Garcia throttle_config_init(&cfg); 387f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 388f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1); 389f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1); 390d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 391f17cfe81SBenoît Canet 3921588ab5dSAlberto Garcia throttle_config_init(&cfg); 393f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 394d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 395f17cfe81SBenoît Canet 3961588ab5dSAlberto Garcia throttle_config_init(&cfg); 397f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1); 398f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1); 399d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 400f17cfe81SBenoît Canet } 401f17cfe81SBenoît Canet 402f17cfe81SBenoît Canet static void test_conflicting_config(void) 403f17cfe81SBenoît Canet { 404f17cfe81SBenoît Canet /* bps average conflicts */ 405f17cfe81SBenoît Canet test_conflicts_for_one_set(false, 406f17cfe81SBenoît Canet THROTTLE_BPS_TOTAL, 407f17cfe81SBenoît Canet THROTTLE_BPS_READ, 408f17cfe81SBenoît Canet THROTTLE_BPS_WRITE); 409f17cfe81SBenoît Canet 410f17cfe81SBenoît Canet /* ops average conflicts */ 411f17cfe81SBenoît Canet test_conflicts_for_one_set(false, 412f17cfe81SBenoît Canet THROTTLE_OPS_TOTAL, 413f17cfe81SBenoît Canet THROTTLE_OPS_READ, 414f17cfe81SBenoît Canet THROTTLE_OPS_WRITE); 415f17cfe81SBenoît Canet 416f17cfe81SBenoît Canet /* bps average conflicts */ 417f17cfe81SBenoît Canet test_conflicts_for_one_set(true, 418f17cfe81SBenoît Canet THROTTLE_BPS_TOTAL, 419f17cfe81SBenoît Canet THROTTLE_BPS_READ, 420f17cfe81SBenoît Canet THROTTLE_BPS_WRITE); 421f17cfe81SBenoît Canet /* ops average conflicts */ 422f17cfe81SBenoît Canet test_conflicts_for_one_set(true, 423f17cfe81SBenoît Canet THROTTLE_OPS_TOTAL, 424f17cfe81SBenoît Canet THROTTLE_OPS_READ, 425f17cfe81SBenoît Canet THROTTLE_OPS_WRITE); 426f17cfe81SBenoît Canet } 427f17cfe81SBenoît Canet /* functions to test the throttle_is_valid function */ 428f17cfe81SBenoît Canet static void test_is_valid_for_value(int value, bool should_be_valid) 429f17cfe81SBenoît Canet { 430f17cfe81SBenoît Canet int is_max, index; 431f17cfe81SBenoît Canet for (is_max = 0; is_max < 2; is_max++) { 432f17cfe81SBenoît Canet for (index = 0; index < BUCKETS_COUNT; index++) { 4331588ab5dSAlberto Garcia throttle_config_init(&cfg); 434f17cfe81SBenoît Canet set_cfg_value(is_max, index, value); 43503ba36c8SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL) == should_be_valid); 436f17cfe81SBenoît Canet } 437f17cfe81SBenoît Canet } 438f17cfe81SBenoît Canet } 439f17cfe81SBenoît Canet 440f17cfe81SBenoît Canet static void test_is_valid(void) 441f17cfe81SBenoît Canet { 44296420a30SMichael Tokarev /* negative numbesr are invalid */ 443f17cfe81SBenoît Canet test_is_valid_for_value(-1, false); 44496420a30SMichael Tokarev /* zero is valid */ 445f17cfe81SBenoît Canet test_is_valid_for_value(0, true); 44696420a30SMichael Tokarev /* positives numbers are valid */ 447f17cfe81SBenoît Canet test_is_valid_for_value(1, true); 448f17cfe81SBenoît Canet } 449f17cfe81SBenoît Canet 450d942feecSAlberto Garcia static void test_ranges(void) 451d942feecSAlberto Garcia { 452d942feecSAlberto Garcia int i; 453d942feecSAlberto Garcia 454d942feecSAlberto Garcia for (i = 0; i < BUCKETS_COUNT; i++) { 455d942feecSAlberto Garcia LeakyBucket *b = &cfg.buckets[i]; 456d942feecSAlberto Garcia throttle_config_init(&cfg); 457d942feecSAlberto Garcia 458d942feecSAlberto Garcia /* avg = 0 means throttling is disabled, but the config is valid */ 459d942feecSAlberto Garcia b->avg = 0; 460d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 461d942feecSAlberto Garcia g_assert(!throttle_enabled(&cfg)); 462d942feecSAlberto Garcia 463d942feecSAlberto Garcia /* These are valid configurations (values <= THROTTLE_VALUE_MAX) */ 464d942feecSAlberto Garcia b->avg = 1; 465d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 466d942feecSAlberto Garcia 467d942feecSAlberto Garcia b->avg = THROTTLE_VALUE_MAX; 468d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 469d942feecSAlberto Garcia 470d942feecSAlberto Garcia b->avg = THROTTLE_VALUE_MAX; 471d942feecSAlberto Garcia b->max = THROTTLE_VALUE_MAX; 472d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 473d942feecSAlberto Garcia 474d942feecSAlberto Garcia /* Values over THROTTLE_VALUE_MAX are not allowed */ 475d942feecSAlberto Garcia b->avg = THROTTLE_VALUE_MAX + 1; 476d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 477d942feecSAlberto Garcia 478d942feecSAlberto Garcia b->avg = THROTTLE_VALUE_MAX; 479d942feecSAlberto Garcia b->max = THROTTLE_VALUE_MAX + 1; 480d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 481d942feecSAlberto Garcia 482d942feecSAlberto Garcia /* burst_length must be between 1 and THROTTLE_VALUE_MAX */ 483d942feecSAlberto Garcia b->avg = 1; 484d942feecSAlberto Garcia b->max = 1; 485d942feecSAlberto Garcia b->burst_length = 0; 486d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 487d942feecSAlberto Garcia 488d942feecSAlberto Garcia b->avg = 1; 489d942feecSAlberto Garcia b->max = 1; 490d942feecSAlberto Garcia b->burst_length = 1; 491d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 492d942feecSAlberto Garcia 493d942feecSAlberto Garcia b->avg = 1; 494d942feecSAlberto Garcia b->max = 1; 495d942feecSAlberto Garcia b->burst_length = THROTTLE_VALUE_MAX; 496d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 497d942feecSAlberto Garcia 498d942feecSAlberto Garcia b->avg = 1; 499d942feecSAlberto Garcia b->max = 1; 500d942feecSAlberto Garcia b->burst_length = THROTTLE_VALUE_MAX + 1; 501d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 502d942feecSAlberto Garcia 503d942feecSAlberto Garcia /* burst_length * max cannot exceed THROTTLE_VALUE_MAX */ 504d942feecSAlberto Garcia b->avg = 1; 505d942feecSAlberto Garcia b->max = 2; 506d942feecSAlberto Garcia b->burst_length = THROTTLE_VALUE_MAX / 2; 507d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 508d942feecSAlberto Garcia 509d942feecSAlberto Garcia b->avg = 1; 510d942feecSAlberto Garcia b->max = 3; 511d942feecSAlberto Garcia b->burst_length = THROTTLE_VALUE_MAX / 2; 512d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 513d942feecSAlberto Garcia 514d942feecSAlberto Garcia b->avg = 1; 515d942feecSAlberto Garcia b->max = THROTTLE_VALUE_MAX; 516d942feecSAlberto Garcia b->burst_length = 1; 517d942feecSAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 518d942feecSAlberto Garcia 519d942feecSAlberto Garcia b->avg = 1; 520d942feecSAlberto Garcia b->max = THROTTLE_VALUE_MAX; 521d942feecSAlberto Garcia b->burst_length = 2; 522d942feecSAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 523d942feecSAlberto Garcia } 524d942feecSAlberto Garcia } 525d942feecSAlberto Garcia 52692e11a17SStefan Hajnoczi static void test_max_is_missing_limit(void) 52792e11a17SStefan Hajnoczi { 52892e11a17SStefan Hajnoczi int i; 52992e11a17SStefan Hajnoczi 53092e11a17SStefan Hajnoczi for (i = 0; i < BUCKETS_COUNT; i++) { 5311588ab5dSAlberto Garcia throttle_config_init(&cfg); 53292e11a17SStefan Hajnoczi cfg.buckets[i].max = 100; 53392e11a17SStefan Hajnoczi cfg.buckets[i].avg = 0; 534d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 53592e11a17SStefan Hajnoczi 53692e11a17SStefan Hajnoczi cfg.buckets[i].max = 0; 53792e11a17SStefan Hajnoczi cfg.buckets[i].avg = 0; 538d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 53992e11a17SStefan Hajnoczi 54092e11a17SStefan Hajnoczi cfg.buckets[i].max = 0; 54192e11a17SStefan Hajnoczi cfg.buckets[i].avg = 100; 542d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 5435fc8c052SAlberto Garcia 5445fc8c052SAlberto Garcia cfg.buckets[i].max = 30; 5455fc8c052SAlberto Garcia cfg.buckets[i].avg = 100; 5465fc8c052SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 5475fc8c052SAlberto Garcia 5485fc8c052SAlberto Garcia cfg.buckets[i].max = 100; 5495fc8c052SAlberto Garcia cfg.buckets[i].avg = 100; 5505fc8c052SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 55192e11a17SStefan Hajnoczi } 55292e11a17SStefan Hajnoczi } 55392e11a17SStefan Hajnoczi 5548860eabdSStefan Hajnoczi static void test_iops_size_is_missing_limit(void) 5558860eabdSStefan Hajnoczi { 5568860eabdSStefan Hajnoczi /* A total/read/write iops limit is required */ 5578860eabdSStefan Hajnoczi throttle_config_init(&cfg); 5588860eabdSStefan Hajnoczi cfg.op_size = 4096; 5598860eabdSStefan Hajnoczi g_assert(!throttle_is_valid(&cfg, NULL)); 5608860eabdSStefan Hajnoczi } 5618860eabdSStefan Hajnoczi 562f17cfe81SBenoît Canet static void test_have_timer(void) 563f17cfe81SBenoît Canet { 5640e5b0a2dSBenoît Canet /* zero structures */ 565f17cfe81SBenoît Canet memset(&ts, 0, sizeof(ts)); 566c61791fcSManos Pitsidianakis memset(tt, 0, sizeof(*tt)); 567f17cfe81SBenoît Canet 56873f395faSStefan Weil /* no timer set should return false */ 569c61791fcSManos Pitsidianakis g_assert(!throttle_timers_are_initialized(tt)); 570f17cfe81SBenoît Canet 5710e5b0a2dSBenoît Canet /* init structures */ 5720e5b0a2dSBenoît Canet throttle_init(&ts); 573c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL, 57413af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 575f17cfe81SBenoît Canet 576f17cfe81SBenoît Canet /* timer set by init should return true */ 577c61791fcSManos Pitsidianakis g_assert(throttle_timers_are_initialized(tt)); 578f17cfe81SBenoît Canet 579c61791fcSManos Pitsidianakis throttle_timers_destroy(tt); 580f17cfe81SBenoît Canet } 581f17cfe81SBenoît Canet 58222524f72SStefan Hajnoczi static void test_detach_attach(void) 58322524f72SStefan Hajnoczi { 5840e5b0a2dSBenoît Canet /* zero structures */ 58522524f72SStefan Hajnoczi memset(&ts, 0, sizeof(ts)); 586c61791fcSManos Pitsidianakis memset(tt, 0, sizeof(*tt)); 58722524f72SStefan Hajnoczi 58822524f72SStefan Hajnoczi /* init the structure */ 5890e5b0a2dSBenoît Canet throttle_init(&ts); 590c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL, 59122524f72SStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 59222524f72SStefan Hajnoczi 59322524f72SStefan Hajnoczi /* timer set by init should return true */ 594c61791fcSManos Pitsidianakis g_assert(throttle_timers_are_initialized(tt)); 59522524f72SStefan Hajnoczi 59622524f72SStefan Hajnoczi /* timer should no longer exist after detaching */ 597c61791fcSManos Pitsidianakis throttle_timers_detach_aio_context(tt); 598c61791fcSManos Pitsidianakis g_assert(!throttle_timers_are_initialized(tt)); 59922524f72SStefan Hajnoczi 60022524f72SStefan Hajnoczi /* timer should exist again after attaching */ 601c61791fcSManos Pitsidianakis throttle_timers_attach_aio_context(tt, ctx); 602c61791fcSManos Pitsidianakis g_assert(throttle_timers_are_initialized(tt)); 60322524f72SStefan Hajnoczi 604c61791fcSManos Pitsidianakis throttle_timers_destroy(tt); 60522524f72SStefan Hajnoczi } 60622524f72SStefan Hajnoczi 607f17cfe81SBenoît Canet static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */ 608f17cfe81SBenoît Canet int size, /* size of the operation to do */ 609f17cfe81SBenoît Canet double avg, /* io limit */ 610f17cfe81SBenoît Canet uint64_t op_size, /* ideal size of an io */ 611f17cfe81SBenoît Canet double total_result, 612f17cfe81SBenoît Canet double read_result, 613f17cfe81SBenoît Canet double write_result) 614f17cfe81SBenoît Canet { 615f17cfe81SBenoît Canet BucketType to_test[2][3] = { { THROTTLE_BPS_TOTAL, 616f17cfe81SBenoît Canet THROTTLE_BPS_READ, 617f17cfe81SBenoît Canet THROTTLE_BPS_WRITE, }, 618f17cfe81SBenoît Canet { THROTTLE_OPS_TOTAL, 619f17cfe81SBenoît Canet THROTTLE_OPS_READ, 620f17cfe81SBenoît Canet THROTTLE_OPS_WRITE, } }; 621f17cfe81SBenoît Canet BucketType index; 622f17cfe81SBenoît Canet int i; 623f17cfe81SBenoît Canet 624ef0aa6afSAndrey Shinkevich throttle_config_init(&cfg); 625ef0aa6afSAndrey Shinkevich 626f17cfe81SBenoît Canet for (i = 0; i < 3; i++) { 627d8573092SAlberto Garcia index = to_test[is_ops][i]; 628f17cfe81SBenoît Canet cfg.buckets[index].avg = avg; 629f17cfe81SBenoît Canet } 630f17cfe81SBenoît Canet 631f17cfe81SBenoît Canet cfg.op_size = op_size; 632f17cfe81SBenoît Canet 6330e5b0a2dSBenoît Canet throttle_init(&ts); 634c61791fcSManos Pitsidianakis throttle_timers_init(tt, ctx, QEMU_CLOCK_VIRTUAL, 63513af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 63627e4cf13SManos Pitsidianakis throttle_config(&ts, QEMU_CLOCK_VIRTUAL, &cfg); 637f17cfe81SBenoît Canet 638f17cfe81SBenoît Canet /* account a read */ 639e76f201fSzhenwei pi throttle_account(&ts, THROTTLE_READ, size); 640f17cfe81SBenoît Canet /* account a write */ 641e76f201fSzhenwei pi throttle_account(&ts, THROTTLE_WRITE, size); 642f17cfe81SBenoît Canet 643f17cfe81SBenoît Canet /* check total result */ 644f17cfe81SBenoît Canet index = to_test[is_ops][0]; 645f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, total_result)) { 646f17cfe81SBenoît Canet return false; 647f17cfe81SBenoît Canet } 648f17cfe81SBenoît Canet 649f17cfe81SBenoît Canet /* check read result */ 650f17cfe81SBenoît Canet index = to_test[is_ops][1]; 651f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, read_result)) { 652f17cfe81SBenoît Canet return false; 653f17cfe81SBenoît Canet } 654f17cfe81SBenoît Canet 655f17cfe81SBenoît Canet /* check write result */ 656f17cfe81SBenoît Canet index = to_test[is_ops][2]; 657f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, write_result)) { 658f17cfe81SBenoît Canet return false; 659f17cfe81SBenoît Canet } 660f17cfe81SBenoît Canet 661c61791fcSManos Pitsidianakis throttle_timers_destroy(tt); 662f17cfe81SBenoît Canet 663f17cfe81SBenoît Canet return true; 664f17cfe81SBenoît Canet } 665f17cfe81SBenoît Canet 666f17cfe81SBenoît Canet static void test_accounting(void) 667f17cfe81SBenoît Canet { 668f17cfe81SBenoît Canet /* tests for bps */ 669f17cfe81SBenoît Canet 670f17cfe81SBenoît Canet /* op of size 1 */ 671f17cfe81SBenoît Canet g_assert(do_test_accounting(false, 672f17cfe81SBenoît Canet 1 * 512, 673f17cfe81SBenoît Canet 150, 674f17cfe81SBenoît Canet 0, 675f17cfe81SBenoît Canet 1024, 676f17cfe81SBenoît Canet 512, 677f17cfe81SBenoît Canet 512)); 678f17cfe81SBenoît Canet 679f17cfe81SBenoît Canet /* op of size 2 */ 680f17cfe81SBenoît Canet g_assert(do_test_accounting(false, 681f17cfe81SBenoît Canet 2 * 512, 682f17cfe81SBenoît Canet 150, 683f17cfe81SBenoît Canet 0, 684f17cfe81SBenoît Canet 2048, 685f17cfe81SBenoît Canet 1024, 686f17cfe81SBenoît Canet 1024)); 687f17cfe81SBenoît Canet 688f17cfe81SBenoît Canet /* op of size 2 and orthogonal parameter change */ 689f17cfe81SBenoît Canet g_assert(do_test_accounting(false, 690f17cfe81SBenoît Canet 2 * 512, 691f17cfe81SBenoît Canet 150, 692f17cfe81SBenoît Canet 17, 693f17cfe81SBenoît Canet 2048, 694f17cfe81SBenoît Canet 1024, 695f17cfe81SBenoît Canet 1024)); 696f17cfe81SBenoît Canet 697f17cfe81SBenoît Canet 698f17cfe81SBenoît Canet /* tests for ops */ 699f17cfe81SBenoît Canet 700f17cfe81SBenoît Canet /* op of size 1 */ 701f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 702f17cfe81SBenoît Canet 1 * 512, 703f17cfe81SBenoît Canet 150, 704f17cfe81SBenoît Canet 0, 705f17cfe81SBenoît Canet 2, 706f17cfe81SBenoît Canet 1, 707f17cfe81SBenoît Canet 1)); 708f17cfe81SBenoît Canet 709f17cfe81SBenoît Canet /* op of size 2 */ 710f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 711f17cfe81SBenoît Canet 2 * 512, 712f17cfe81SBenoît Canet 150, 713f17cfe81SBenoît Canet 0, 714f17cfe81SBenoît Canet 2, 715f17cfe81SBenoît Canet 1, 716f17cfe81SBenoît Canet 1)); 717f17cfe81SBenoît Canet 718f17cfe81SBenoît Canet /* jumbo op accounting fragmentation : size 64 with op size of 13 units */ 719f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 720f17cfe81SBenoît Canet 64 * 512, 721f17cfe81SBenoît Canet 150, 722f17cfe81SBenoît Canet 13 * 512, 723f17cfe81SBenoît Canet (64.0 * 2) / 13, 724f17cfe81SBenoît Canet (64.0 / 13), 725f17cfe81SBenoît Canet (64.0 / 13))); 726f17cfe81SBenoît Canet 727f17cfe81SBenoît Canet /* same with orthogonal parameters changes */ 728f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 729f17cfe81SBenoît Canet 64 * 512, 730f17cfe81SBenoît Canet 300, 731f17cfe81SBenoît Canet 13 * 512, 732f17cfe81SBenoît Canet (64.0 * 2) / 13, 733f17cfe81SBenoît Canet (64.0 / 13), 734f17cfe81SBenoît Canet (64.0 / 13))); 735f17cfe81SBenoît Canet } 736f17cfe81SBenoît Canet 7371fee955fSAlberto Garcia static void test_groups(void) 7381fee955fSAlberto Garcia { 7391fee955fSAlberto Garcia ThrottleConfig cfg1, cfg2; 740a5614993SKevin Wolf BlockBackend *blk1, *blk2, *blk3; 74127ccdd52SKevin Wolf BlockBackendPublic *blkp1, *blkp2, *blkp3; 742022cdc9fSManos Pitsidianakis ThrottleGroupMember *tgm1, *tgm2, *tgm3; 7431fee955fSAlberto Garcia 7442807c0cdSKevin Wolf /* No actual I/O is performed on these devices */ 745d861ab3aSKevin Wolf blk1 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); 746d861ab3aSKevin Wolf blk2 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); 747d861ab3aSKevin Wolf blk3 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); 748a5614993SKevin Wolf 74927ccdd52SKevin Wolf blkp1 = blk_get_public(blk1); 75027ccdd52SKevin Wolf blkp2 = blk_get_public(blk2); 75127ccdd52SKevin Wolf blkp3 = blk_get_public(blk3); 75227ccdd52SKevin Wolf 753022cdc9fSManos Pitsidianakis tgm1 = &blkp1->throttle_group_member; 754022cdc9fSManos Pitsidianakis tgm2 = &blkp2->throttle_group_member; 755022cdc9fSManos Pitsidianakis tgm3 = &blkp3->throttle_group_member; 7561fee955fSAlberto Garcia 757022cdc9fSManos Pitsidianakis g_assert(tgm1->throttle_state == NULL); 758022cdc9fSManos Pitsidianakis g_assert(tgm2->throttle_state == NULL); 759022cdc9fSManos Pitsidianakis g_assert(tgm3->throttle_state == NULL); 7601fee955fSAlberto Garcia 761c61791fcSManos Pitsidianakis throttle_group_register_tgm(tgm1, "bar", blk_get_aio_context(blk1)); 762c61791fcSManos Pitsidianakis throttle_group_register_tgm(tgm2, "foo", blk_get_aio_context(blk2)); 763c61791fcSManos Pitsidianakis throttle_group_register_tgm(tgm3, "bar", blk_get_aio_context(blk3)); 7641fee955fSAlberto Garcia 765022cdc9fSManos Pitsidianakis g_assert(tgm1->throttle_state != NULL); 766022cdc9fSManos Pitsidianakis g_assert(tgm2->throttle_state != NULL); 767022cdc9fSManos Pitsidianakis g_assert(tgm3->throttle_state != NULL); 768022cdc9fSManos Pitsidianakis 769022cdc9fSManos Pitsidianakis g_assert(!strcmp(throttle_group_get_name(tgm1), "bar")); 770022cdc9fSManos Pitsidianakis g_assert(!strcmp(throttle_group_get_name(tgm2), "foo")); 771022cdc9fSManos Pitsidianakis g_assert(tgm1->throttle_state == tgm3->throttle_state); 7721fee955fSAlberto Garcia 7731fee955fSAlberto Garcia /* Setting the config of a group member affects the whole group */ 7741588ab5dSAlberto Garcia throttle_config_init(&cfg1); 7751fee955fSAlberto Garcia cfg1.buckets[THROTTLE_BPS_READ].avg = 500000; 7761fee955fSAlberto Garcia cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000; 7771fee955fSAlberto Garcia cfg1.buckets[THROTTLE_OPS_READ].avg = 20000; 7781fee955fSAlberto Garcia cfg1.buckets[THROTTLE_OPS_WRITE].avg = 12000; 779022cdc9fSManos Pitsidianakis throttle_group_config(tgm1, &cfg1); 7801fee955fSAlberto Garcia 781022cdc9fSManos Pitsidianakis throttle_group_get_config(tgm1, &cfg1); 782022cdc9fSManos Pitsidianakis throttle_group_get_config(tgm3, &cfg2); 7831fee955fSAlberto Garcia g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1))); 7841fee955fSAlberto Garcia 7851fee955fSAlberto Garcia cfg2.buckets[THROTTLE_BPS_READ].avg = 4547; 7861fee955fSAlberto Garcia cfg2.buckets[THROTTLE_BPS_WRITE].avg = 1349; 7871fee955fSAlberto Garcia cfg2.buckets[THROTTLE_OPS_READ].avg = 123; 7881fee955fSAlberto Garcia cfg2.buckets[THROTTLE_OPS_WRITE].avg = 86; 789022cdc9fSManos Pitsidianakis throttle_group_config(tgm3, &cfg1); 7901fee955fSAlberto Garcia 791022cdc9fSManos Pitsidianakis throttle_group_get_config(tgm1, &cfg1); 792022cdc9fSManos Pitsidianakis throttle_group_get_config(tgm3, &cfg2); 7931fee955fSAlberto Garcia g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1))); 7941fee955fSAlberto Garcia 795022cdc9fSManos Pitsidianakis throttle_group_unregister_tgm(tgm1); 796022cdc9fSManos Pitsidianakis throttle_group_unregister_tgm(tgm2); 797022cdc9fSManos Pitsidianakis throttle_group_unregister_tgm(tgm3); 7981fee955fSAlberto Garcia 799022cdc9fSManos Pitsidianakis g_assert(tgm1->throttle_state == NULL); 800022cdc9fSManos Pitsidianakis g_assert(tgm2->throttle_state == NULL); 801022cdc9fSManos Pitsidianakis g_assert(tgm3->throttle_state == NULL); 8021fee955fSAlberto Garcia } 8031fee955fSAlberto Garcia 804f17cfe81SBenoît Canet int main(int argc, char **argv) 805f17cfe81SBenoît Canet { 80673eaa047SMarkus Armbruster qemu_init_main_loop(&error_fatal); 8071fee955fSAlberto Garcia ctx = qemu_get_aio_context(); 8081fee955fSAlberto Garcia bdrv_init(); 809432d889eSManos Pitsidianakis module_call_init(MODULE_INIT_QOM); 81013af91ebSStefan Hajnoczi 811f17cfe81SBenoît Canet do {} while (g_main_context_iteration(NULL, false)); 812f17cfe81SBenoît Canet 813f17cfe81SBenoît Canet /* tests in the same order as the header function declarations */ 814f17cfe81SBenoît Canet g_test_init(&argc, &argv, NULL); 815f17cfe81SBenoît Canet g_test_add_func("/throttle/leak_bucket", test_leak_bucket); 816f17cfe81SBenoît Canet g_test_add_func("/throttle/compute_wait", test_compute_wait); 817f17cfe81SBenoît Canet g_test_add_func("/throttle/init", test_init); 81802add531Szhenwei pi g_test_add_func("/throttle/init_readonly", test_init_readonly); 81902add531Szhenwei pi g_test_add_func("/throttle/init_writeonly", test_init_writeonly); 820f17cfe81SBenoît Canet g_test_add_func("/throttle/destroy", test_destroy); 821f17cfe81SBenoît Canet g_test_add_func("/throttle/have_timer", test_have_timer); 82222524f72SStefan Hajnoczi g_test_add_func("/throttle/detach_attach", test_detach_attach); 823f17cfe81SBenoît Canet g_test_add_func("/throttle/config/enabled", test_enabled); 824f17cfe81SBenoît Canet g_test_add_func("/throttle/config/conflicting", test_conflicting_config); 825f17cfe81SBenoît Canet g_test_add_func("/throttle/config/is_valid", test_is_valid); 826d942feecSAlberto Garcia g_test_add_func("/throttle/config/ranges", test_ranges); 82792e11a17SStefan Hajnoczi g_test_add_func("/throttle/config/max", test_max_is_missing_limit); 8288860eabdSStefan Hajnoczi g_test_add_func("/throttle/config/iops_size", 8298860eabdSStefan Hajnoczi test_iops_size_is_missing_limit); 830f17cfe81SBenoît Canet g_test_add_func("/throttle/config_functions", test_config_functions); 831f17cfe81SBenoît Canet g_test_add_func("/throttle/accounting", test_accounting); 8321fee955fSAlberto Garcia g_test_add_func("/throttle/groups", test_groups); 833f17cfe81SBenoît Canet return g_test_run(); 834f17cfe81SBenoît Canet } 835f17cfe81SBenoît Canet 836