resource_counter.txt 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. The Resource Counter
  2. The resource counter, declared at include/linux/res_counter.h,
  3. is supposed to facilitate the resource management by controllers
  4. by providing common stuff for accounting.
  5. This "stuff" includes the res_counter structure and routines
  6. to work with it.
  7. 1. Crucial parts of the res_counter structure
  8. a. unsigned long long usage
  9. The usage value shows the amount of a resource that is consumed
  10. by a group at a given time. The units of measurement should be
  11. determined by the controller that uses this counter. E.g. it can
  12. be bytes, items or any other unit the controller operates on.
  13. b. unsigned long long max_usage
  14. The maximal value of the usage over time.
  15. This value is useful when gathering statistical information about
  16. the particular group, as it shows the actual resource requirements
  17. for a particular group, not just some usage snapshot.
  18. c. unsigned long long limit
  19. The maximal allowed amount of resource to consume by the group. In
  20. case the group requests for more resources, so that the usage value
  21. would exceed the limit, the resource allocation is rejected (see
  22. the next section).
  23. d. unsigned long long failcnt
  24. The failcnt stands for "failures counter". This is the number of
  25. resource allocation attempts that failed.
  26. c. spinlock_t lock
  27. Protects changes of the above values.
  28. 2. Basic accounting routines
  29. a. void res_counter_init(struct res_counter *rc)
  30. Initializes the resource counter. As usual, should be the first
  31. routine called for a new counter.
  32. b. int res_counter_charge[_locked]
  33. (struct res_counter *rc, unsigned long val)
  34. When a resource is about to be allocated it has to be accounted
  35. with the appropriate resource counter (controller should determine
  36. which one to use on its own). This operation is called "charging".
  37. This is not very important which operation - resource allocation
  38. or charging - is performed first, but
  39. * if the allocation is performed first, this may create a
  40. temporary resource over-usage by the time resource counter is
  41. charged;
  42. * if the charging is performed first, then it should be uncharged
  43. on error path (if the one is called).
  44. c. void res_counter_uncharge[_locked]
  45. (struct res_counter *rc, unsigned long val)
  46. When a resource is released (freed) it should be de-accounted
  47. from the resource counter it was accounted to. This is called
  48. "uncharging".
  49. The _locked routines imply that the res_counter->lock is taken.
  50. 2.1 Other accounting routines
  51. There are more routines that may help you with common needs, like
  52. checking whether the limit is reached or resetting the max_usage
  53. value. They are all declared in include/linux/res_counter.h.
  54. 3. Analyzing the resource counter registrations
  55. a. If the failcnt value constantly grows, this means that the counter's
  56. limit is too tight. Either the group is misbehaving and consumes too
  57. many resources, or the configuration is not suitable for the group
  58. and the limit should be increased.
  59. b. The max_usage value can be used to quickly tune the group. One may
  60. set the limits to maximal values and either load the container with
  61. a common pattern or leave one for a while. After this the max_usage
  62. value shows the amount of memory the container would require during
  63. its common activity.
  64. Setting the limit a bit above this value gives a pretty good
  65. configuration that works in most of the cases.
  66. c. If the max_usage is much less than the limit, but the failcnt value
  67. is growing, then the group tries to allocate a big chunk of resource
  68. at once.
  69. d. If the max_usage is much less than the limit, but the failcnt value
  70. is 0, then this group is given too high limit, that it does not
  71. require. It is better to lower the limit a bit leaving more resource
  72. for other groups.
  73. 4. Communication with the control groups subsystem (cgroups)
  74. All the resource controllers that are using cgroups and resource counters
  75. should provide files (in the cgroup filesystem) to work with the resource
  76. counter fields. They are recommended to adhere to the following rules:
  77. a. File names
  78. Field name File name
  79. ---------------------------------------------------
  80. usage usage_in_<unit_of_measurement>
  81. max_usage max_usage_in_<unit_of_measurement>
  82. limit limit_in_<unit_of_measurement>
  83. failcnt failcnt
  84. lock no file :)
  85. b. Reading from file should show the corresponding field value in the
  86. appropriate format.
  87. c. Writing to file
  88. Field Expected behavior
  89. ----------------------------------
  90. usage prohibited
  91. max_usage reset to usage
  92. limit set the limit
  93. failcnt reset to zero
  94. 5. Usage example
  95. a. Declare a task group (take a look at cgroups subsystem for this) and
  96. fold a res_counter into it
  97. struct my_group {
  98. struct res_counter res;
  99. <other fields>
  100. }
  101. b. Put hooks in resource allocation/release paths
  102. int alloc_something(...)
  103. {
  104. if (res_counter_charge(res_counter_ptr, amount) < 0)
  105. return -ENOMEM;
  106. <allocate the resource and return to the caller>
  107. }
  108. void release_something(...)
  109. {
  110. res_counter_uncharge(res_counter_ptr, amount);
  111. <release the resource>
  112. }
  113. In order to keep the usage value self-consistent, both the
  114. "res_counter_ptr" and the "amount" in release_something() should be
  115. the same as they were in the alloc_something() when the releasing
  116. resource was allocated.
  117. c. Provide the way to read res_counter values and set them (the cgroups
  118. still can help with it).
  119. c. Compile and run :)