static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */ int size, /* size of the operation to do */ double avg, /* io limit */ uint64_t op_size, /* ideal size of an io */ double total_result, double read_result, double write_result) { BucketType to_test[2][3] = { { THROTTLE_BPS_TOTAL, THROTTLE_BPS_READ, THROTTLE_BPS_WRITE, }, { THROTTLE_OPS_TOTAL, THROTTLE_OPS_READ, THROTTLE_OPS_WRITE, } }; ThrottleConfig cfg; BucketType index; int i; for (i = 0; i < 3; i++) { BucketType index = to_test[is_ops][i]; cfg.buckets[index].avg = avg; } cfg.op_size = op_size; throttle_init(&ts); throttle_timers_init(&tt, ctx, QEMU_CLOCK_VIRTUAL, read_timer_cb, write_timer_cb, &ts); throttle_config(&ts, &tt, &cfg); /* account a read */ throttle_account(&ts, false, size); /* account a write */ throttle_account(&ts, true, size); /* check total result */ index = to_test[is_ops][0]; if (!double_cmp(ts.cfg.buckets[index].level, total_result)) { return false; } /* check read result */ index = to_test[is_ops][1]; if (!double_cmp(ts.cfg.buckets[index].level, read_result)) { return false; } /* check write result */ index = to_test[is_ops][2]; if (!double_cmp(ts.cfg.buckets[index].level, write_result)) { return false; } throttle_timers_destroy(&tt); return true; }
void fsdev_throttle_init(FsThrottle *fst) { if (throttle_enabled(&fst->cfg)) { throttle_init(&fst->ts); throttle_timers_init(&fst->tt, qemu_get_aio_context(), QEMU_CLOCK_REALTIME, fsdev_throttle_read_timer_cb, fsdev_throttle_write_timer_cb, fst); throttle_config(&fst->ts, QEMU_CLOCK_REALTIME, &fst->cfg); qemu_co_queue_init(&fst->throttled_reqs[0]); qemu_co_queue_init(&fst->throttled_reqs[1]); } }
/* function to test throttle_config and throttle_get_config */ static void test_config_functions(void) { int i; ThrottleConfig orig_cfg, final_cfg; orig_cfg.buckets[THROTTLE_BPS_TOTAL].avg = 153; orig_cfg.buckets[THROTTLE_BPS_READ].avg = 56; orig_cfg.buckets[THROTTLE_BPS_WRITE].avg = 1; orig_cfg.buckets[THROTTLE_OPS_TOTAL].avg = 150; orig_cfg.buckets[THROTTLE_OPS_READ].avg = 69; orig_cfg.buckets[THROTTLE_OPS_WRITE].avg = 23; orig_cfg.buckets[THROTTLE_BPS_TOTAL].max = 0; /* should be corrected */ orig_cfg.buckets[THROTTLE_BPS_READ].max = 1; /* should not be corrected */ orig_cfg.buckets[THROTTLE_BPS_WRITE].max = 120; orig_cfg.buckets[THROTTLE_OPS_TOTAL].max = 150; orig_cfg.buckets[THROTTLE_OPS_READ].max = 400; orig_cfg.buckets[THROTTLE_OPS_WRITE].max = 500; orig_cfg.buckets[THROTTLE_BPS_TOTAL].level = 45; orig_cfg.buckets[THROTTLE_BPS_READ].level = 65; orig_cfg.buckets[THROTTLE_BPS_WRITE].level = 23; orig_cfg.buckets[THROTTLE_OPS_TOTAL].level = 1; orig_cfg.buckets[THROTTLE_OPS_READ].level = 90; orig_cfg.buckets[THROTTLE_OPS_WRITE].level = 75; orig_cfg.op_size = 1; throttle_init(&ts, QEMU_CLOCK_VIRTUAL, read_timer_cb, write_timer_cb, &ts); /* structure reset by throttle_init previous_leak should be null */ g_assert(!ts.previous_leak); throttle_config(&ts, &orig_cfg); /* has previous leak been initialized by throttle_config ? */ g_assert(ts.previous_leak); /* get back the fixed configuration */ throttle_get_config(&ts, &final_cfg); throttle_destroy(&ts); g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].avg == 153); g_assert(final_cfg.buckets[THROTTLE_BPS_READ].avg == 56); g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].avg == 1); g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].avg == 150); g_assert(final_cfg.buckets[THROTTLE_OPS_READ].avg == 69); g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].avg == 23); g_assert(final_cfg.buckets[THROTTLE_BPS_TOTAL].max == 15.3);/* fixed */ g_assert(final_cfg.buckets[THROTTLE_BPS_READ].max == 1); /* not fixed */ g_assert(final_cfg.buckets[THROTTLE_BPS_WRITE].max == 120); g_assert(final_cfg.buckets[THROTTLE_OPS_TOTAL].max == 150); g_assert(final_cfg.buckets[THROTTLE_OPS_READ].max == 400); g_assert(final_cfg.buckets[THROTTLE_OPS_WRITE].max == 500); g_assert(final_cfg.op_size == 1); /* check bucket have been cleared */ for (i = 0; i < BUCKETS_COUNT; i++) { g_assert(!final_cfg.buckets[i].level); } }