qemu-fsdev-throttle.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * Fsdev Throttle
  3. *
  4. * Copyright (C) 2016 Huawei Technologies Duesseldorf GmbH
  5. *
  6. * Author: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>
  7. *
  8. * This work is licensed under the terms of the GNU GPL, version 2 or
  9. * (at your option) any later version.
  10. *
  11. * See the COPYING file in the top-level directory for details.
  12. *
  13. */
  14. #include "qemu/osdep.h"
  15. #include "qemu/error-report.h"
  16. #include "qemu-fsdev-throttle.h"
  17. #include "qemu/iov.h"
  18. #include "qemu/main-loop.h"
  19. #include "qemu/option.h"
  20. static void fsdev_throttle_read_timer_cb(void *opaque)
  21. {
  22. FsThrottle *fst = opaque;
  23. qemu_co_enter_next(&fst->throttled_reqs[false], NULL);
  24. }
  25. static void fsdev_throttle_write_timer_cb(void *opaque)
  26. {
  27. FsThrottle *fst = opaque;
  28. qemu_co_enter_next(&fst->throttled_reqs[true], NULL);
  29. }
  30. int fsdev_throttle_parse_opts(QemuOpts *opts, FsThrottle *fst, Error **errp)
  31. {
  32. throttle_config_init(&fst->cfg);
  33. fst->cfg.buckets[THROTTLE_BPS_TOTAL].avg =
  34. qemu_opt_get_number(opts, "throttling.bps-total", 0);
  35. fst->cfg.buckets[THROTTLE_BPS_READ].avg =
  36. qemu_opt_get_number(opts, "throttling.bps-read", 0);
  37. fst->cfg.buckets[THROTTLE_BPS_WRITE].avg =
  38. qemu_opt_get_number(opts, "throttling.bps-write", 0);
  39. fst->cfg.buckets[THROTTLE_OPS_TOTAL].avg =
  40. qemu_opt_get_number(opts, "throttling.iops-total", 0);
  41. fst->cfg.buckets[THROTTLE_OPS_READ].avg =
  42. qemu_opt_get_number(opts, "throttling.iops-read", 0);
  43. fst->cfg.buckets[THROTTLE_OPS_WRITE].avg =
  44. qemu_opt_get_number(opts, "throttling.iops-write", 0);
  45. fst->cfg.buckets[THROTTLE_BPS_TOTAL].max =
  46. qemu_opt_get_number(opts, "throttling.bps-total-max", 0);
  47. fst->cfg.buckets[THROTTLE_BPS_READ].max =
  48. qemu_opt_get_number(opts, "throttling.bps-read-max", 0);
  49. fst->cfg.buckets[THROTTLE_BPS_WRITE].max =
  50. qemu_opt_get_number(opts, "throttling.bps-write-max", 0);
  51. fst->cfg.buckets[THROTTLE_OPS_TOTAL].max =
  52. qemu_opt_get_number(opts, "throttling.iops-total-max", 0);
  53. fst->cfg.buckets[THROTTLE_OPS_READ].max =
  54. qemu_opt_get_number(opts, "throttling.iops-read-max", 0);
  55. fst->cfg.buckets[THROTTLE_OPS_WRITE].max =
  56. qemu_opt_get_number(opts, "throttling.iops-write-max", 0);
  57. fst->cfg.buckets[THROTTLE_BPS_TOTAL].burst_length =
  58. qemu_opt_get_number(opts, "throttling.bps-total-max-length", 1);
  59. fst->cfg.buckets[THROTTLE_BPS_READ].burst_length =
  60. qemu_opt_get_number(opts, "throttling.bps-read-max-length", 1);
  61. fst->cfg.buckets[THROTTLE_BPS_WRITE].burst_length =
  62. qemu_opt_get_number(opts, "throttling.bps-write-max-length", 1);
  63. fst->cfg.buckets[THROTTLE_OPS_TOTAL].burst_length =
  64. qemu_opt_get_number(opts, "throttling.iops-total-max-length", 1);
  65. fst->cfg.buckets[THROTTLE_OPS_READ].burst_length =
  66. qemu_opt_get_number(opts, "throttling.iops-read-max-length", 1);
  67. fst->cfg.buckets[THROTTLE_OPS_WRITE].burst_length =
  68. qemu_opt_get_number(opts, "throttling.iops-write-max-length", 1);
  69. fst->cfg.op_size =
  70. qemu_opt_get_number(opts, "throttling.iops-size", 0);
  71. return throttle_is_valid(&fst->cfg, errp) ? 0 : -1;
  72. }
  73. void fsdev_throttle_init(FsThrottle *fst)
  74. {
  75. if (throttle_enabled(&fst->cfg)) {
  76. throttle_init(&fst->ts);
  77. throttle_timers_init(&fst->tt,
  78. qemu_get_aio_context(),
  79. QEMU_CLOCK_REALTIME,
  80. fsdev_throttle_read_timer_cb,
  81. fsdev_throttle_write_timer_cb,
  82. fst);
  83. throttle_config(&fst->ts, QEMU_CLOCK_REALTIME, &fst->cfg);
  84. qemu_co_queue_init(&fst->throttled_reqs[0]);
  85. qemu_co_queue_init(&fst->throttled_reqs[1]);
  86. }
  87. }
  88. void coroutine_fn fsdev_co_throttle_request(FsThrottle *fst, bool is_write,
  89. struct iovec *iov, int iovcnt)
  90. {
  91. if (throttle_enabled(&fst->cfg)) {
  92. if (throttle_schedule_timer(&fst->ts, &fst->tt, is_write) ||
  93. !qemu_co_queue_empty(&fst->throttled_reqs[is_write])) {
  94. qemu_co_queue_wait(&fst->throttled_reqs[is_write], NULL);
  95. }
  96. throttle_account(&fst->ts, is_write, iov_size(iov, iovcnt));
  97. if (!qemu_co_queue_empty(&fst->throttled_reqs[is_write]) &&
  98. !throttle_schedule_timer(&fst->ts, &fst->tt, is_write)) {
  99. qemu_co_queue_next(&fst->throttled_reqs[is_write]);
  100. }
  101. }
  102. }
  103. void fsdev_throttle_cleanup(FsThrottle *fst)
  104. {
  105. if (throttle_enabled(&fst->cfg)) {
  106. throttle_timers_destroy(&fst->tt);
  107. }
  108. }