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" 211fee955fSAlberto Garcia #include "block/throttle-groups.h" 2231dce3ccSKevin Wolf #include "sysemu/block-backend.h" 23f17cfe81SBenoît Canet 24748bfb4eSStefan Weil static AioContext *ctx; 25748bfb4eSStefan Weil static LeakyBucket bkt; 26748bfb4eSStefan Weil static ThrottleConfig cfg; 27748bfb4eSStefan Weil static ThrottleState ts; 280e5b0a2dSBenoît Canet static ThrottleTimers tt; 29f17cfe81SBenoît Canet 3073f395faSStefan Weil /* useful function */ 31f17cfe81SBenoît Canet static bool double_cmp(double x, double y) 32f17cfe81SBenoît Canet { 33f17cfe81SBenoît Canet return fabsl(x - y) < 1e-6; 34f17cfe81SBenoît Canet } 35f17cfe81SBenoît Canet 36f17cfe81SBenoît Canet /* tests for single bucket operations */ 37f17cfe81SBenoît Canet static void test_leak_bucket(void) 38f17cfe81SBenoît Canet { 391588ab5dSAlberto Garcia throttle_config_init(&cfg); 401588ab5dSAlberto Garcia bkt = cfg.buckets[THROTTLE_BPS_TOTAL]; 411588ab5dSAlberto Garcia 42f17cfe81SBenoît Canet /* set initial value */ 43f17cfe81SBenoît Canet bkt.avg = 150; 44f17cfe81SBenoît Canet bkt.max = 15; 45f17cfe81SBenoît Canet bkt.level = 1.5; 46f17cfe81SBenoît Canet 47f17cfe81SBenoît Canet /* leak an op work of time */ 4813566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150); 49f17cfe81SBenoît Canet g_assert(bkt.avg == 150); 50f17cfe81SBenoît Canet g_assert(bkt.max == 15); 51f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0.5)); 52f17cfe81SBenoît Canet 53f17cfe81SBenoît Canet /* leak again emptying the bucket */ 5413566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150); 55f17cfe81SBenoît Canet g_assert(bkt.avg == 150); 56f17cfe81SBenoît Canet g_assert(bkt.max == 15); 57f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0)); 58f17cfe81SBenoît Canet 59f17cfe81SBenoît Canet /* check that the bucket level won't go lower */ 6013566fe3SStefan Hajnoczi throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 150); 61f17cfe81SBenoît Canet g_assert(bkt.avg == 150); 62f17cfe81SBenoît Canet g_assert(bkt.max == 15); 63f17cfe81SBenoît Canet g_assert(double_cmp(bkt.level, 0)); 64eb8a1a1cSAlberto Garcia 65eb8a1a1cSAlberto Garcia /* check that burst_level leaks correctly */ 66eb8a1a1cSAlberto Garcia bkt.burst_level = 6; 67eb8a1a1cSAlberto Garcia bkt.max = 250; 68eb8a1a1cSAlberto Garcia bkt.burst_length = 2; /* otherwise burst_level will not leak */ 69eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100); 70eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 3.5)); 71eb8a1a1cSAlberto Garcia 72eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100); 73eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 1)); 74eb8a1a1cSAlberto Garcia 75eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100); 76eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 0)); 77eb8a1a1cSAlberto Garcia 78eb8a1a1cSAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100); 79eb8a1a1cSAlberto Garcia g_assert(double_cmp(bkt.burst_level, 0)); 80f17cfe81SBenoît Canet } 81f17cfe81SBenoît Canet 82f17cfe81SBenoît Canet static void test_compute_wait(void) 83f17cfe81SBenoît Canet { 84f9d05885SAlberto Garcia unsigned i; 85f17cfe81SBenoît Canet int64_t wait; 86f17cfe81SBenoît Canet int64_t result; 87f17cfe81SBenoît Canet 881588ab5dSAlberto Garcia throttle_config_init(&cfg); 891588ab5dSAlberto Garcia bkt = cfg.buckets[THROTTLE_BPS_TOTAL]; 901588ab5dSAlberto Garcia 91f17cfe81SBenoît Canet /* no operation limit set */ 92f17cfe81SBenoît Canet bkt.avg = 0; 93f17cfe81SBenoît Canet bkt.max = 15; 94f17cfe81SBenoît Canet bkt.level = 1.5; 95f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 96f17cfe81SBenoît Canet g_assert(!wait); 97f17cfe81SBenoît Canet 98f17cfe81SBenoît Canet /* zero delta */ 99f17cfe81SBenoît Canet bkt.avg = 150; 100f17cfe81SBenoît Canet bkt.max = 15; 101f17cfe81SBenoît Canet bkt.level = 15; 102f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 103f17cfe81SBenoît Canet g_assert(!wait); 104f17cfe81SBenoît Canet 105f17cfe81SBenoît Canet /* below zero delta */ 106f17cfe81SBenoît Canet bkt.avg = 150; 107f17cfe81SBenoît Canet bkt.max = 15; 108f17cfe81SBenoît Canet bkt.level = 9; 109f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 110f17cfe81SBenoît Canet g_assert(!wait); 111f17cfe81SBenoît Canet 112f17cfe81SBenoît Canet /* half an operation above max */ 113f17cfe81SBenoît Canet bkt.avg = 150; 114f17cfe81SBenoît Canet bkt.max = 15; 115f17cfe81SBenoît Canet bkt.level = 15.5; 116f17cfe81SBenoît Canet wait = throttle_compute_wait(&bkt); 117f17cfe81SBenoît Canet /* time required to do half an operation */ 11813566fe3SStefan Hajnoczi result = (int64_t) NANOSECONDS_PER_SECOND / 150 / 2; 119f17cfe81SBenoît Canet g_assert(wait == result); 120f9d05885SAlberto Garcia 121f9d05885SAlberto Garcia /* Perform I/O for 2.2 seconds at a rate of bkt.max */ 122f9d05885SAlberto Garcia bkt.burst_length = 2; 123f9d05885SAlberto Garcia bkt.level = 0; 124f9d05885SAlberto Garcia bkt.avg = 10; 125f9d05885SAlberto Garcia bkt.max = 200; 126f9d05885SAlberto Garcia for (i = 0; i < 22; i++) { 127f9d05885SAlberto Garcia double units = bkt.max / 10; 128f9d05885SAlberto Garcia bkt.level += units; 129f9d05885SAlberto Garcia bkt.burst_level += units; 130f9d05885SAlberto Garcia throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 10); 131f9d05885SAlberto Garcia wait = throttle_compute_wait(&bkt); 132f9d05885SAlberto Garcia g_assert(double_cmp(bkt.burst_level, 0)); 133f9d05885SAlberto Garcia g_assert(double_cmp(bkt.level, (i + 1) * (bkt.max - bkt.avg) / 10)); 134f9d05885SAlberto Garcia /* We can do bursts for the 2 seconds we have configured in 135f9d05885SAlberto Garcia * burst_length. We have 100 extra miliseconds of burst 136f9d05885SAlberto Garcia * because bkt.level has been leaking during this time. 137f9d05885SAlberto Garcia * After that, we have to wait. */ 138f9d05885SAlberto Garcia result = i < 21 ? 0 : 1.8 * NANOSECONDS_PER_SECOND; 139f9d05885SAlberto Garcia g_assert(wait == result); 140f9d05885SAlberto Garcia } 141f17cfe81SBenoît Canet } 142f17cfe81SBenoît Canet 143f17cfe81SBenoît Canet /* functions to test ThrottleState initialization/destroy methods */ 144f17cfe81SBenoît Canet static void read_timer_cb(void *opaque) 145f17cfe81SBenoît Canet { 146f17cfe81SBenoît Canet } 147f17cfe81SBenoît Canet 148f17cfe81SBenoît Canet static void write_timer_cb(void *opaque) 149f17cfe81SBenoît Canet { 150f17cfe81SBenoît Canet } 151f17cfe81SBenoît Canet 152f17cfe81SBenoît Canet static void test_init(void) 153f17cfe81SBenoît Canet { 154f17cfe81SBenoît Canet int i; 155f17cfe81SBenoît Canet 1560e5b0a2dSBenoît Canet /* fill the structures with crap */ 157f17cfe81SBenoît Canet memset(&ts, 1, sizeof(ts)); 1580e5b0a2dSBenoît Canet memset(&tt, 1, sizeof(tt)); 159f17cfe81SBenoît Canet 1600e5b0a2dSBenoît Canet /* init structures */ 1610e5b0a2dSBenoît Canet throttle_init(&ts); 1620e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 16313af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 164f17cfe81SBenoît Canet 165f17cfe81SBenoît Canet /* check initialized fields */ 1660e5b0a2dSBenoît Canet g_assert(tt.clock_type == QEMU_CLOCK_VIRTUAL); 1670e5b0a2dSBenoît Canet g_assert(tt.timers[0]); 1680e5b0a2dSBenoît Canet g_assert(tt.timers[1]); 169f17cfe81SBenoît Canet 170f17cfe81SBenoît Canet /* check other fields where cleared */ 171f17cfe81SBenoît Canet g_assert(!ts.previous_leak); 172f17cfe81SBenoît Canet g_assert(!ts.cfg.op_size); 173f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 174f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].avg); 175f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].max); 176f17cfe81SBenoît Canet g_assert(!ts.cfg.buckets[i].level); 177f17cfe81SBenoît Canet } 178f17cfe81SBenoît Canet 1790e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 180f17cfe81SBenoît Canet } 181f17cfe81SBenoît Canet 182f17cfe81SBenoît Canet static void test_destroy(void) 183f17cfe81SBenoît Canet { 184f17cfe81SBenoît Canet int i; 1850e5b0a2dSBenoît Canet throttle_init(&ts); 1860e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 18713af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 1880e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 189f17cfe81SBenoît Canet for (i = 0; i < 2; i++) { 1900e5b0a2dSBenoît Canet g_assert(!tt.timers[i]); 191f17cfe81SBenoît Canet } 192f17cfe81SBenoît Canet } 193f17cfe81SBenoît Canet 194f17cfe81SBenoît Canet /* function to test throttle_config and throttle_get_config */ 195f17cfe81SBenoît Canet static void test_config_functions(void) 196f17cfe81SBenoît Canet { 197f17cfe81SBenoît Canet int i; 198f17cfe81SBenoît Canet ThrottleConfig orig_cfg, final_cfg; 199f17cfe81SBenoît Canet 200f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_TOTAL].avg = 153; 201f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_READ].avg = 56; 202f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].avg = 1; 203f17cfe81SBenoît Canet 204f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].avg = 150; 205f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].avg = 69; 206f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].avg = 23; 207f17cfe81SBenoît Canet 208f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_TOTAL].max = 0; /* should be corrected */ 209f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_READ].max = 1; /* should not be corrected */ 210f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].max = 120; 211f17cfe81SBenoît Canet 212f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].max = 150; 213f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].max = 400; 214f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].max = 500; 215f17cfe81SBenoît Canet 216f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_TOTAL].level = 45; 217f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_READ].level = 65; 218f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_BPS_WRITE].level = 23; 219f17cfe81SBenoît Canet 220f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_TOTAL].level = 1; 221f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_READ].level = 90; 222f17cfe81SBenoît Canet orig_cfg.buckets[THROTTLE_OPS_WRITE].level = 75; 223f17cfe81SBenoît Canet 224f17cfe81SBenoît Canet orig_cfg.op_size = 1; 225f17cfe81SBenoît Canet 2260e5b0a2dSBenoît Canet throttle_init(&ts); 2270e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 22813af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 229f17cfe81SBenoît Canet /* structure reset by throttle_init previous_leak should be null */ 230f17cfe81SBenoît Canet g_assert(!ts.previous_leak); 2310e5b0a2dSBenoît Canet throttle_config(&ts, &tt, &orig_cfg); 232f17cfe81SBenoît Canet 233f17cfe81SBenoît Canet /* has previous leak been initialized by throttle_config ? */ 234f17cfe81SBenoît Canet g_assert(ts.previous_leak); 235f17cfe81SBenoît Canet 236f17cfe81SBenoît Canet /* get back the fixed configuration */ 237f17cfe81SBenoît Canet throttle_get_config(&ts, &final_cfg); 238f17cfe81SBenoît Canet 2390e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 240f17cfe81SBenoît Canet 241f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].avg == 153); 242f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_READ].avg == 56); 243f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].avg == 1); 244f17cfe81SBenoît Canet 245f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].avg == 150); 246f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_READ].avg == 69); 247f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].avg == 23); 248f17cfe81SBenoît Canet 249f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].max == 15.3);/* fixed */ 250f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_READ].max == 1); /* not fixed */ 251f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].max == 120); 252f17cfe81SBenoît Canet 253f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].max == 150); 254f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_READ].max == 400); 255f17cfe81SBenoît Canet g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].max == 500); 256f17cfe81SBenoît Canet 257f17cfe81SBenoît Canet g_assert(final_cfg.op_size == 1); 258f17cfe81SBenoît Canet 259f17cfe81SBenoît Canet /* check bucket have been cleared */ 260f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 261f17cfe81SBenoît Canet g_assert(!final_cfg.buckets[i].level); 262f17cfe81SBenoît Canet } 263f17cfe81SBenoît Canet } 264f17cfe81SBenoît Canet 265f17cfe81SBenoît Canet /* functions to test is throttle is enabled by a config */ 266f17cfe81SBenoît Canet static void set_cfg_value(bool is_max, int index, int value) 267f17cfe81SBenoît Canet { 268f17cfe81SBenoît Canet if (is_max) { 269f17cfe81SBenoît Canet cfg.buckets[index].max = value; 2706f9b6d57SAlberto Garcia /* If max is set, avg should never be 0 */ 2716f9b6d57SAlberto Garcia cfg.buckets[index].avg = MAX(cfg.buckets[index].avg, 1); 272f17cfe81SBenoît Canet } else { 273f17cfe81SBenoît Canet cfg.buckets[index].avg = value; 274f17cfe81SBenoît Canet } 275f17cfe81SBenoît Canet } 276f17cfe81SBenoît Canet 277f17cfe81SBenoît Canet static void test_enabled(void) 278f17cfe81SBenoît Canet { 279f17cfe81SBenoît Canet int i; 280f17cfe81SBenoît Canet 2811588ab5dSAlberto Garcia throttle_config_init(&cfg); 282f17cfe81SBenoît Canet g_assert(!throttle_enabled(&cfg)); 283f17cfe81SBenoît Canet 284f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 2851588ab5dSAlberto Garcia throttle_config_init(&cfg); 286f17cfe81SBenoît Canet set_cfg_value(false, i, 150); 287f17cfe81SBenoît Canet g_assert(throttle_enabled(&cfg)); 288f17cfe81SBenoît Canet } 289f17cfe81SBenoît Canet 290f17cfe81SBenoît Canet for (i = 0; i < BUCKETS_COUNT; i++) { 2911588ab5dSAlberto Garcia throttle_config_init(&cfg); 292f17cfe81SBenoît Canet set_cfg_value(false, i, -150); 293f17cfe81SBenoît Canet g_assert(!throttle_enabled(&cfg)); 294f17cfe81SBenoît Canet } 295f17cfe81SBenoît Canet } 296f17cfe81SBenoît Canet 297f17cfe81SBenoît Canet /* tests functions for throttle_conflicting */ 298f17cfe81SBenoît Canet 299f17cfe81SBenoît Canet static void test_conflicts_for_one_set(bool is_max, 300f17cfe81SBenoît Canet int total, 301f17cfe81SBenoît Canet int read, 302f17cfe81SBenoît Canet int write) 303f17cfe81SBenoît Canet { 3041588ab5dSAlberto Garcia throttle_config_init(&cfg); 305d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 306f17cfe81SBenoît Canet 307f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 308f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1); 309d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 310f17cfe81SBenoît Canet 3111588ab5dSAlberto Garcia throttle_config_init(&cfg); 312f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 313f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1); 314d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 315f17cfe81SBenoît Canet 3161588ab5dSAlberto Garcia throttle_config_init(&cfg); 317f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 318f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1); 319f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1); 320d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 321f17cfe81SBenoît Canet 3221588ab5dSAlberto Garcia throttle_config_init(&cfg); 323f17cfe81SBenoît Canet set_cfg_value(is_max, total, 1); 324d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 325f17cfe81SBenoît Canet 3261588ab5dSAlberto Garcia throttle_config_init(&cfg); 327f17cfe81SBenoît Canet set_cfg_value(is_max, read, 1); 328f17cfe81SBenoît Canet set_cfg_value(is_max, write, 1); 329d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 330f17cfe81SBenoît Canet } 331f17cfe81SBenoît Canet 332f17cfe81SBenoît Canet static void test_conflicting_config(void) 333f17cfe81SBenoît Canet { 334f17cfe81SBenoît Canet /* bps average conflicts */ 335f17cfe81SBenoît Canet test_conflicts_for_one_set(false, 336f17cfe81SBenoît Canet THROTTLE_BPS_TOTAL, 337f17cfe81SBenoît Canet THROTTLE_BPS_READ, 338f17cfe81SBenoît Canet THROTTLE_BPS_WRITE); 339f17cfe81SBenoît Canet 340f17cfe81SBenoît Canet /* ops average conflicts */ 341f17cfe81SBenoît Canet test_conflicts_for_one_set(false, 342f17cfe81SBenoît Canet THROTTLE_OPS_TOTAL, 343f17cfe81SBenoît Canet THROTTLE_OPS_READ, 344f17cfe81SBenoît Canet THROTTLE_OPS_WRITE); 345f17cfe81SBenoît Canet 346f17cfe81SBenoît Canet /* bps average conflicts */ 347f17cfe81SBenoît Canet test_conflicts_for_one_set(true, 348f17cfe81SBenoît Canet THROTTLE_BPS_TOTAL, 349f17cfe81SBenoît Canet THROTTLE_BPS_READ, 350f17cfe81SBenoît Canet THROTTLE_BPS_WRITE); 351f17cfe81SBenoît Canet /* ops average conflicts */ 352f17cfe81SBenoît Canet test_conflicts_for_one_set(true, 353f17cfe81SBenoît Canet THROTTLE_OPS_TOTAL, 354f17cfe81SBenoît Canet THROTTLE_OPS_READ, 355f17cfe81SBenoît Canet THROTTLE_OPS_WRITE); 356f17cfe81SBenoît Canet } 357f17cfe81SBenoît Canet /* functions to test the throttle_is_valid function */ 358f17cfe81SBenoît Canet static void test_is_valid_for_value(int value, bool should_be_valid) 359f17cfe81SBenoît Canet { 360f17cfe81SBenoît Canet int is_max, index; 361f17cfe81SBenoît Canet for (is_max = 0; is_max < 2; is_max++) { 362f17cfe81SBenoît Canet for (index = 0; index < BUCKETS_COUNT; index++) { 3631588ab5dSAlberto Garcia throttle_config_init(&cfg); 364f17cfe81SBenoît Canet set_cfg_value(is_max, index, value); 36503ba36c8SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL) == should_be_valid); 366f17cfe81SBenoît Canet } 367f17cfe81SBenoît Canet } 368f17cfe81SBenoît Canet } 369f17cfe81SBenoît Canet 370f17cfe81SBenoît Canet static void test_is_valid(void) 371f17cfe81SBenoît Canet { 372f17cfe81SBenoît Canet /* negative number are invalid */ 373f17cfe81SBenoît Canet test_is_valid_for_value(-1, false); 374f17cfe81SBenoît Canet /* zero are valids */ 375f17cfe81SBenoît Canet test_is_valid_for_value(0, true); 376f17cfe81SBenoît Canet /* positives numers are valids */ 377f17cfe81SBenoît Canet test_is_valid_for_value(1, true); 378f17cfe81SBenoît Canet } 379f17cfe81SBenoît Canet 38092e11a17SStefan Hajnoczi static void test_max_is_missing_limit(void) 38192e11a17SStefan Hajnoczi { 38292e11a17SStefan Hajnoczi int i; 38392e11a17SStefan Hajnoczi 38492e11a17SStefan Hajnoczi for (i = 0; i < BUCKETS_COUNT; i++) { 3851588ab5dSAlberto Garcia throttle_config_init(&cfg); 38692e11a17SStefan Hajnoczi cfg.buckets[i].max = 100; 38792e11a17SStefan Hajnoczi cfg.buckets[i].avg = 0; 388d5851089SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 38992e11a17SStefan Hajnoczi 39092e11a17SStefan Hajnoczi cfg.buckets[i].max = 0; 39192e11a17SStefan Hajnoczi cfg.buckets[i].avg = 0; 392d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 39392e11a17SStefan Hajnoczi 39492e11a17SStefan Hajnoczi cfg.buckets[i].max = 0; 39592e11a17SStefan Hajnoczi cfg.buckets[i].avg = 100; 396d5851089SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 3975fc8c052SAlberto Garcia 3985fc8c052SAlberto Garcia cfg.buckets[i].max = 30; 3995fc8c052SAlberto Garcia cfg.buckets[i].avg = 100; 4005fc8c052SAlberto Garcia g_assert(!throttle_is_valid(&cfg, NULL)); 4015fc8c052SAlberto Garcia 4025fc8c052SAlberto Garcia cfg.buckets[i].max = 100; 4035fc8c052SAlberto Garcia cfg.buckets[i].avg = 100; 4045fc8c052SAlberto Garcia g_assert(throttle_is_valid(&cfg, NULL)); 40592e11a17SStefan Hajnoczi } 40692e11a17SStefan Hajnoczi } 40792e11a17SStefan Hajnoczi 4088860eabdSStefan Hajnoczi static void test_iops_size_is_missing_limit(void) 4098860eabdSStefan Hajnoczi { 4108860eabdSStefan Hajnoczi /* A total/read/write iops limit is required */ 4118860eabdSStefan Hajnoczi throttle_config_init(&cfg); 4128860eabdSStefan Hajnoczi cfg.op_size = 4096; 4138860eabdSStefan Hajnoczi g_assert(!throttle_is_valid(&cfg, NULL)); 4148860eabdSStefan Hajnoczi } 4158860eabdSStefan Hajnoczi 416f17cfe81SBenoît Canet static void test_have_timer(void) 417f17cfe81SBenoît Canet { 4180e5b0a2dSBenoît Canet /* zero structures */ 419f17cfe81SBenoît Canet memset(&ts, 0, sizeof(ts)); 4200e5b0a2dSBenoît Canet memset(&tt, 0, sizeof(tt)); 421f17cfe81SBenoît Canet 42273f395faSStefan Weil /* no timer set should return false */ 4230e5b0a2dSBenoît Canet g_assert(!throttle_timers_are_initialized(&tt)); 424f17cfe81SBenoît Canet 4250e5b0a2dSBenoît Canet /* init structures */ 4260e5b0a2dSBenoît Canet throttle_init(&ts); 4270e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 42813af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 429f17cfe81SBenoît Canet 430f17cfe81SBenoît Canet /* timer set by init should return true */ 4310e5b0a2dSBenoît Canet g_assert(throttle_timers_are_initialized(&tt)); 432f17cfe81SBenoît Canet 4330e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 434f17cfe81SBenoît Canet } 435f17cfe81SBenoît Canet 43622524f72SStefan Hajnoczi static void test_detach_attach(void) 43722524f72SStefan Hajnoczi { 4380e5b0a2dSBenoît Canet /* zero structures */ 43922524f72SStefan Hajnoczi memset(&ts, 0, sizeof(ts)); 4400e5b0a2dSBenoît Canet memset(&tt, 0, sizeof(tt)); 44122524f72SStefan Hajnoczi 44222524f72SStefan Hajnoczi /* init the structure */ 4430e5b0a2dSBenoît Canet throttle_init(&ts); 4440e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 44522524f72SStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 44622524f72SStefan Hajnoczi 44722524f72SStefan Hajnoczi /* timer set by init should return true */ 4480e5b0a2dSBenoît Canet g_assert(throttle_timers_are_initialized(&tt)); 44922524f72SStefan Hajnoczi 45022524f72SStefan Hajnoczi /* timer should no longer exist after detaching */ 4510e5b0a2dSBenoît Canet throttle_timers_detach_aio_context(&tt); 4520e5b0a2dSBenoît Canet g_assert(!throttle_timers_are_initialized(&tt)); 45322524f72SStefan Hajnoczi 45422524f72SStefan Hajnoczi /* timer should exist again after attaching */ 4550e5b0a2dSBenoît Canet throttle_timers_attach_aio_context(&tt, ctx); 4560e5b0a2dSBenoît Canet g_assert(throttle_timers_are_initialized(&tt)); 45722524f72SStefan Hajnoczi 4580e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 45922524f72SStefan Hajnoczi } 46022524f72SStefan Hajnoczi 461f17cfe81SBenoît Canet static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */ 462f17cfe81SBenoît Canet int size, /* size of the operation to do */ 463f17cfe81SBenoît Canet double avg, /* io limit */ 464f17cfe81SBenoît Canet uint64_t op_size, /* ideal size of an io */ 465f17cfe81SBenoît Canet double total_result, 466f17cfe81SBenoît Canet double read_result, 467f17cfe81SBenoît Canet double write_result) 468f17cfe81SBenoît Canet { 469f17cfe81SBenoît Canet BucketType to_test[2][3] = { { THROTTLE_BPS_TOTAL, 470f17cfe81SBenoît Canet THROTTLE_BPS_READ, 471f17cfe81SBenoît Canet THROTTLE_BPS_WRITE, }, 472f17cfe81SBenoît Canet { THROTTLE_OPS_TOTAL, 473f17cfe81SBenoît Canet THROTTLE_OPS_READ, 474f17cfe81SBenoît Canet THROTTLE_OPS_WRITE, } }; 475f17cfe81SBenoît Canet ThrottleConfig cfg; 476f17cfe81SBenoît Canet BucketType index; 477f17cfe81SBenoît Canet int i; 478f17cfe81SBenoît Canet 479f17cfe81SBenoît Canet for (i = 0; i < 3; i++) { 480f17cfe81SBenoît Canet BucketType index = to_test[is_ops][i]; 481f17cfe81SBenoît Canet cfg.buckets[index].avg = avg; 482f17cfe81SBenoît Canet } 483f17cfe81SBenoît Canet 484f17cfe81SBenoît Canet cfg.op_size = op_size; 485f17cfe81SBenoît Canet 4860e5b0a2dSBenoît Canet throttle_init(&ts); 4870e5b0a2dSBenoît Canet throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, 48813af91ebSStefan Hajnoczi read_timer_cb, write_timer_cb, &ts); 4890e5b0a2dSBenoît Canet throttle_config(&ts, &tt, &cfg); 490f17cfe81SBenoît Canet 491f17cfe81SBenoît Canet /* account a read */ 492f17cfe81SBenoît Canet throttle_account(&ts, false, size); 493f17cfe81SBenoît Canet /* account a write */ 494f17cfe81SBenoît Canet throttle_account(&ts, true, size); 495f17cfe81SBenoît Canet 496f17cfe81SBenoît Canet /* check total result */ 497f17cfe81SBenoît Canet index = to_test[is_ops][0]; 498f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, total_result)) { 499f17cfe81SBenoît Canet return false; 500f17cfe81SBenoît Canet } 501f17cfe81SBenoît Canet 502f17cfe81SBenoît Canet /* check read result */ 503f17cfe81SBenoît Canet index = to_test[is_ops][1]; 504f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, read_result)) { 505f17cfe81SBenoît Canet return false; 506f17cfe81SBenoît Canet } 507f17cfe81SBenoît Canet 508f17cfe81SBenoît Canet /* check write result */ 509f17cfe81SBenoît Canet index = to_test[is_ops][2]; 510f17cfe81SBenoît Canet if (!double_cmp(ts.cfg.buckets[index].level, write_result)) { 511f17cfe81SBenoît Canet return false; 512f17cfe81SBenoît Canet } 513f17cfe81SBenoît Canet 5140e5b0a2dSBenoît Canet throttle_timers_destroy(&tt); 515f17cfe81SBenoît Canet 516f17cfe81SBenoît Canet return true; 517f17cfe81SBenoît Canet } 518f17cfe81SBenoît Canet 519f17cfe81SBenoît Canet static void test_accounting(void) 520f17cfe81SBenoît Canet { 521f17cfe81SBenoît Canet /* tests for bps */ 522f17cfe81SBenoît Canet 523f17cfe81SBenoît Canet /* op of size 1 */ 524f17cfe81SBenoît Canet g_assert(do_test_accounting(false, 525f17cfe81SBenoît Canet 1 * 512, 526f17cfe81SBenoît Canet 150, 527f17cfe81SBenoît Canet 0, 528f17cfe81SBenoît Canet 1024, 529f17cfe81SBenoît Canet 512, 530f17cfe81SBenoît Canet 512)); 531f17cfe81SBenoît Canet 532f17cfe81SBenoît Canet /* op of size 2 */ 533f17cfe81SBenoît Canet g_assert(do_test_accounting(false, 534f17cfe81SBenoît Canet 2 * 512, 535f17cfe81SBenoît Canet 150, 536f17cfe81SBenoît Canet 0, 537f17cfe81SBenoît Canet 2048, 538f17cfe81SBenoît Canet 1024, 539f17cfe81SBenoît Canet 1024)); 540f17cfe81SBenoît Canet 541f17cfe81SBenoît Canet /* op of size 2 and orthogonal parameter change */ 542f17cfe81SBenoît Canet g_assert(do_test_accounting(false, 543f17cfe81SBenoît Canet 2 * 512, 544f17cfe81SBenoît Canet 150, 545f17cfe81SBenoît Canet 17, 546f17cfe81SBenoît Canet 2048, 547f17cfe81SBenoît Canet 1024, 548f17cfe81SBenoît Canet 1024)); 549f17cfe81SBenoît Canet 550f17cfe81SBenoît Canet 551f17cfe81SBenoît Canet /* tests for ops */ 552f17cfe81SBenoît Canet 553f17cfe81SBenoît Canet /* op of size 1 */ 554f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 555f17cfe81SBenoît Canet 1 * 512, 556f17cfe81SBenoît Canet 150, 557f17cfe81SBenoît Canet 0, 558f17cfe81SBenoît Canet 2, 559f17cfe81SBenoît Canet 1, 560f17cfe81SBenoît Canet 1)); 561f17cfe81SBenoît Canet 562f17cfe81SBenoît Canet /* op of size 2 */ 563f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 564f17cfe81SBenoît Canet 2 * 512, 565f17cfe81SBenoît Canet 150, 566f17cfe81SBenoît Canet 0, 567f17cfe81SBenoît Canet 2, 568f17cfe81SBenoît Canet 1, 569f17cfe81SBenoît Canet 1)); 570f17cfe81SBenoît Canet 571f17cfe81SBenoît Canet /* jumbo op accounting fragmentation : size 64 with op size of 13 units */ 572f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 573f17cfe81SBenoît Canet 64 * 512, 574f17cfe81SBenoît Canet 150, 575f17cfe81SBenoît Canet 13 * 512, 576f17cfe81SBenoît Canet (64.0 * 2) / 13, 577f17cfe81SBenoît Canet (64.0 / 13), 578f17cfe81SBenoît Canet (64.0 / 13))); 579f17cfe81SBenoît Canet 580f17cfe81SBenoît Canet /* same with orthogonal parameters changes */ 581f17cfe81SBenoît Canet g_assert(do_test_accounting(true, 582f17cfe81SBenoît Canet 64 * 512, 583f17cfe81SBenoît Canet 300, 584f17cfe81SBenoît Canet 13 * 512, 585f17cfe81SBenoît Canet (64.0 * 2) / 13, 586f17cfe81SBenoît Canet (64.0 / 13), 587f17cfe81SBenoît Canet (64.0 / 13))); 588f17cfe81SBenoît Canet } 589f17cfe81SBenoît Canet 5901fee955fSAlberto Garcia static void test_groups(void) 5911fee955fSAlberto Garcia { 5921fee955fSAlberto Garcia ThrottleConfig cfg1, cfg2; 593a5614993SKevin Wolf BlockBackend *blk1, *blk2, *blk3; 59427ccdd52SKevin Wolf BlockBackendPublic *blkp1, *blkp2, *blkp3; 5951fee955fSAlberto Garcia 596*6d0eb64dSKevin Wolf /* FIXME Use real permissions */ 597*6d0eb64dSKevin Wolf blk1 = blk_new(0, BLK_PERM_ALL); 598*6d0eb64dSKevin Wolf blk2 = blk_new(0, BLK_PERM_ALL); 599*6d0eb64dSKevin Wolf blk3 = blk_new(0, BLK_PERM_ALL); 600a5614993SKevin Wolf 60127ccdd52SKevin Wolf blkp1 = blk_get_public(blk1); 60227ccdd52SKevin Wolf blkp2 = blk_get_public(blk2); 60327ccdd52SKevin Wolf blkp3 = blk_get_public(blk3); 60427ccdd52SKevin Wolf 60527ccdd52SKevin Wolf g_assert(blkp1->throttle_state == NULL); 60627ccdd52SKevin Wolf g_assert(blkp2->throttle_state == NULL); 60727ccdd52SKevin Wolf g_assert(blkp3->throttle_state == NULL); 6081fee955fSAlberto Garcia 60931dce3ccSKevin Wolf throttle_group_register_blk(blk1, "bar"); 61031dce3ccSKevin Wolf throttle_group_register_blk(blk2, "foo"); 61131dce3ccSKevin Wolf throttle_group_register_blk(blk3, "bar"); 6121fee955fSAlberto Garcia 61327ccdd52SKevin Wolf g_assert(blkp1->throttle_state != NULL); 61427ccdd52SKevin Wolf g_assert(blkp2->throttle_state != NULL); 61527ccdd52SKevin Wolf g_assert(blkp3->throttle_state != NULL); 6161fee955fSAlberto Garcia 61749d2165dSKevin Wolf g_assert(!strcmp(throttle_group_get_name(blk1), "bar")); 61849d2165dSKevin Wolf g_assert(!strcmp(throttle_group_get_name(blk2), "foo")); 61927ccdd52SKevin Wolf g_assert(blkp1->throttle_state == blkp3->throttle_state); 6201fee955fSAlberto Garcia 6211fee955fSAlberto Garcia /* Setting the config of a group member affects the whole group */ 6221588ab5dSAlberto Garcia throttle_config_init(&cfg1); 6231fee955fSAlberto Garcia cfg1.buckets[THROTTLE_BPS_READ].avg = 500000; 6241fee955fSAlberto Garcia cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000; 6251fee955fSAlberto Garcia cfg1.buckets[THROTTLE_OPS_READ].avg = 20000; 6261fee955fSAlberto Garcia cfg1.buckets[THROTTLE_OPS_WRITE].avg = 12000; 62797148076SKevin Wolf throttle_group_config(blk1, &cfg1); 6281fee955fSAlberto Garcia 62997148076SKevin Wolf throttle_group_get_config(blk1, &cfg1); 63097148076SKevin Wolf throttle_group_get_config(blk3, &cfg2); 6311fee955fSAlberto Garcia g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1))); 6321fee955fSAlberto Garcia 6331fee955fSAlberto Garcia cfg2.buckets[THROTTLE_BPS_READ].avg = 4547; 6341fee955fSAlberto Garcia cfg2.buckets[THROTTLE_BPS_WRITE].avg = 1349; 6351fee955fSAlberto Garcia cfg2.buckets[THROTTLE_OPS_READ].avg = 123; 6361fee955fSAlberto Garcia cfg2.buckets[THROTTLE_OPS_WRITE].avg = 86; 63797148076SKevin Wolf throttle_group_config(blk3, &cfg1); 6381fee955fSAlberto Garcia 63997148076SKevin Wolf throttle_group_get_config(blk1, &cfg1); 64097148076SKevin Wolf throttle_group_get_config(blk3, &cfg2); 6411fee955fSAlberto Garcia g_assert(!memcmp(&cfg1, &cfg2, sizeof(cfg1))); 6421fee955fSAlberto Garcia 64331dce3ccSKevin Wolf throttle_group_unregister_blk(blk1); 64431dce3ccSKevin Wolf throttle_group_unregister_blk(blk2); 64531dce3ccSKevin Wolf throttle_group_unregister_blk(blk3); 6461fee955fSAlberto Garcia 64727ccdd52SKevin Wolf g_assert(blkp1->throttle_state == NULL); 64827ccdd52SKevin Wolf g_assert(blkp2->throttle_state == NULL); 64927ccdd52SKevin Wolf g_assert(blkp3->throttle_state == NULL); 6501fee955fSAlberto Garcia } 6511fee955fSAlberto Garcia 652f17cfe81SBenoît Canet int main(int argc, char **argv) 653f17cfe81SBenoît Canet { 65473eaa047SMarkus Armbruster qemu_init_main_loop(&error_fatal); 6551fee955fSAlberto Garcia ctx = qemu_get_aio_context(); 6561fee955fSAlberto Garcia bdrv_init(); 65713af91ebSStefan Hajnoczi 658f17cfe81SBenoît Canet do {} while (g_main_context_iteration(NULL, false)); 659f17cfe81SBenoît Canet 660f17cfe81SBenoît Canet /* tests in the same order as the header function declarations */ 661f17cfe81SBenoît Canet g_test_init(&argc, &argv, NULL); 662f17cfe81SBenoît Canet g_test_add_func("/throttle/leak_bucket", test_leak_bucket); 663f17cfe81SBenoît Canet g_test_add_func("/throttle/compute_wait", test_compute_wait); 664f17cfe81SBenoît Canet g_test_add_func("/throttle/init", test_init); 665f17cfe81SBenoît Canet g_test_add_func("/throttle/destroy", test_destroy); 666f17cfe81SBenoît Canet g_test_add_func("/throttle/have_timer", test_have_timer); 66722524f72SStefan Hajnoczi g_test_add_func("/throttle/detach_attach", test_detach_attach); 668f17cfe81SBenoît Canet g_test_add_func("/throttle/config/enabled", test_enabled); 669f17cfe81SBenoît Canet g_test_add_func("/throttle/config/conflicting", test_conflicting_config); 670f17cfe81SBenoît Canet g_test_add_func("/throttle/config/is_valid", test_is_valid); 67192e11a17SStefan Hajnoczi g_test_add_func("/throttle/config/max", test_max_is_missing_limit); 6728860eabdSStefan Hajnoczi g_test_add_func("/throttle/config/iops_size", 6738860eabdSStefan Hajnoczi test_iops_size_is_missing_limit); 674f17cfe81SBenoît Canet g_test_add_func("/throttle/config_functions", test_config_functions); 675f17cfe81SBenoît Canet g_test_add_func("/throttle/accounting", test_accounting); 6761fee955fSAlberto Garcia g_test_add_func("/throttle/groups", test_groups); 677f17cfe81SBenoît Canet return g_test_run(); 678f17cfe81SBenoît Canet } 679f17cfe81SBenoît Canet 680