test-throttle.c 23 KB

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