bpf_memcontrol.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Memory Controller-related BPF kfuncs and auxiliary code
  4. *
  5. * Author: Roman Gushchin <roman.gushchin@linux.dev>
  6. */
  7. #include <linux/memcontrol.h>
  8. #include <linux/bpf.h>
  9. __bpf_kfunc_start_defs();
  10. /**
  11. * bpf_get_root_mem_cgroup - Returns a pointer to the root memory cgroup
  12. *
  13. * The function has KF_ACQUIRE semantics, even though the root memory
  14. * cgroup is never destroyed after being created and doesn't require
  15. * reference counting. And it's perfectly safe to pass it to
  16. * bpf_put_mem_cgroup()
  17. *
  18. * Return: A pointer to the root memory cgroup.
  19. */
  20. __bpf_kfunc struct mem_cgroup *bpf_get_root_mem_cgroup(void)
  21. {
  22. if (mem_cgroup_disabled())
  23. return NULL;
  24. /* css_get() is not needed */
  25. return root_mem_cgroup;
  26. }
  27. /**
  28. * bpf_get_mem_cgroup - Get a reference to a memory cgroup
  29. * @css: pointer to the css structure
  30. *
  31. * It's fine to pass a css which belongs to any cgroup controller,
  32. * e.g. unified hierarchy's main css.
  33. *
  34. * Implements KF_ACQUIRE semantics.
  35. *
  36. * Return: A pointer to a mem_cgroup structure after bumping
  37. * the corresponding css's reference counter.
  38. */
  39. __bpf_kfunc struct mem_cgroup *
  40. bpf_get_mem_cgroup(struct cgroup_subsys_state *css)
  41. {
  42. struct mem_cgroup *memcg = NULL;
  43. bool rcu_unlock = false;
  44. if (mem_cgroup_disabled() || !root_mem_cgroup)
  45. return NULL;
  46. if (root_mem_cgroup->css.ss != css->ss) {
  47. struct cgroup *cgroup = css->cgroup;
  48. int ssid = root_mem_cgroup->css.ss->id;
  49. rcu_read_lock();
  50. rcu_unlock = true;
  51. css = rcu_dereference_raw(cgroup->subsys[ssid]);
  52. }
  53. if (css && css_tryget(css))
  54. memcg = container_of(css, struct mem_cgroup, css);
  55. if (rcu_unlock)
  56. rcu_read_unlock();
  57. return memcg;
  58. }
  59. /**
  60. * bpf_put_mem_cgroup - Put a reference to a memory cgroup
  61. * @memcg: memory cgroup to release
  62. *
  63. * Releases a previously acquired memcg reference.
  64. * Implements KF_RELEASE semantics.
  65. */
  66. __bpf_kfunc void bpf_put_mem_cgroup(struct mem_cgroup *memcg)
  67. {
  68. css_put(&memcg->css);
  69. }
  70. /**
  71. * bpf_mem_cgroup_vm_events - Read memory cgroup's vm event counter
  72. * @memcg: memory cgroup
  73. * @event: event id
  74. *
  75. * Allows to read memory cgroup event counters.
  76. *
  77. * Return: The current value of the corresponding events counter.
  78. */
  79. __bpf_kfunc unsigned long bpf_mem_cgroup_vm_events(struct mem_cgroup *memcg,
  80. enum vm_event_item event)
  81. {
  82. if (unlikely(!memcg_vm_event_item_valid(event)))
  83. return (unsigned long)-1;
  84. return memcg_events(memcg, event);
  85. }
  86. /**
  87. * bpf_mem_cgroup_usage - Read memory cgroup's usage
  88. * @memcg: memory cgroup
  89. *
  90. * Please, note that the root memory cgroup it special and is exempt
  91. * from the memory accounting. The returned value is a sum of sub-cgroup's
  92. * usages and it not reflecting the size of the root memory cgroup itself.
  93. * If you need to get an approximation, you can use root level statistics:
  94. * e.g. NR_FILE_PAGES + NR_ANON_MAPPED.
  95. *
  96. * Return: The current memory cgroup size in bytes.
  97. */
  98. __bpf_kfunc unsigned long bpf_mem_cgroup_usage(struct mem_cgroup *memcg)
  99. {
  100. return page_counter_read(&memcg->memory) * PAGE_SIZE;
  101. }
  102. /**
  103. * bpf_mem_cgroup_memory_events - Read memory cgroup's memory event value
  104. * @memcg: memory cgroup
  105. * @event: memory event id
  106. *
  107. * Return: The current value of the memory event counter.
  108. */
  109. __bpf_kfunc unsigned long bpf_mem_cgroup_memory_events(struct mem_cgroup *memcg,
  110. enum memcg_memory_event event)
  111. {
  112. if (unlikely(event >= MEMCG_NR_MEMORY_EVENTS))
  113. return (unsigned long)-1;
  114. return atomic_long_read(&memcg->memory_events[event]);
  115. }
  116. /**
  117. * bpf_mem_cgroup_page_state - Read memory cgroup's page state counter
  118. * @memcg: memory cgroup
  119. * @idx: counter idx
  120. *
  121. * Allows to read memory cgroup statistics. The output is in bytes.
  122. *
  123. * Return: The value of the page state counter in bytes.
  124. */
  125. __bpf_kfunc unsigned long bpf_mem_cgroup_page_state(struct mem_cgroup *memcg, int idx)
  126. {
  127. if (unlikely(!memcg_stat_item_valid(idx)))
  128. return (unsigned long)-1;
  129. return memcg_page_state_output(memcg, idx);
  130. }
  131. /**
  132. * bpf_mem_cgroup_flush_stats - Flush memory cgroup's statistics
  133. * @memcg: memory cgroup
  134. *
  135. * Propagate memory cgroup's statistics up the cgroup tree.
  136. */
  137. __bpf_kfunc void bpf_mem_cgroup_flush_stats(struct mem_cgroup *memcg)
  138. {
  139. mem_cgroup_flush_stats(memcg);
  140. }
  141. __bpf_kfunc_end_defs();
  142. BTF_KFUNCS_START(bpf_memcontrol_kfuncs)
  143. BTF_ID_FLAGS(func, bpf_get_root_mem_cgroup, KF_ACQUIRE | KF_RET_NULL)
  144. BTF_ID_FLAGS(func, bpf_get_mem_cgroup, KF_ACQUIRE | KF_RET_NULL | KF_RCU)
  145. BTF_ID_FLAGS(func, bpf_put_mem_cgroup, KF_RELEASE)
  146. BTF_ID_FLAGS(func, bpf_mem_cgroup_vm_events)
  147. BTF_ID_FLAGS(func, bpf_mem_cgroup_memory_events)
  148. BTF_ID_FLAGS(func, bpf_mem_cgroup_usage)
  149. BTF_ID_FLAGS(func, bpf_mem_cgroup_page_state)
  150. BTF_ID_FLAGS(func, bpf_mem_cgroup_flush_stats, KF_SLEEPABLE)
  151. BTF_KFUNCS_END(bpf_memcontrol_kfuncs)
  152. static const struct btf_kfunc_id_set bpf_memcontrol_kfunc_set = {
  153. .owner = THIS_MODULE,
  154. .set = &bpf_memcontrol_kfuncs,
  155. };
  156. static int __init bpf_memcontrol_init(void)
  157. {
  158. int err;
  159. err = register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC,
  160. &bpf_memcontrol_kfunc_set);
  161. if (err)
  162. pr_warn("error while registering bpf memcontrol kfuncs: %d", err);
  163. return err;
  164. }
  165. late_initcall(bpf_memcontrol_init);