swap_cgroup.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/swap_cgroup.h>
  3. #include <linux/vmalloc.h>
  4. #include <linux/mm.h>
  5. #include <linux/swapops.h> /* depends on mm.h include */
  6. static DEFINE_MUTEX(swap_cgroup_mutex);
  7. /* Pack two cgroup id (short) of two entries in one swap_cgroup (atomic_t) */
  8. #define ID_PER_SC (sizeof(struct swap_cgroup) / sizeof(unsigned short))
  9. #define ID_SHIFT (BITS_PER_TYPE(unsigned short))
  10. #define ID_MASK (BIT(ID_SHIFT) - 1)
  11. struct swap_cgroup {
  12. atomic_t ids;
  13. };
  14. struct swap_cgroup_ctrl {
  15. struct swap_cgroup *map;
  16. };
  17. static struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES];
  18. static unsigned short __swap_cgroup_id_lookup(struct swap_cgroup *map,
  19. pgoff_t offset)
  20. {
  21. unsigned int shift = (offset % ID_PER_SC) * ID_SHIFT;
  22. unsigned int old_ids = atomic_read(&map[offset / ID_PER_SC].ids);
  23. BUILD_BUG_ON(!is_power_of_2(ID_PER_SC));
  24. BUILD_BUG_ON(sizeof(struct swap_cgroup) != sizeof(atomic_t));
  25. return (old_ids >> shift) & ID_MASK;
  26. }
  27. static unsigned short __swap_cgroup_id_xchg(struct swap_cgroup *map,
  28. pgoff_t offset,
  29. unsigned short new_id)
  30. {
  31. unsigned short old_id;
  32. struct swap_cgroup *sc = &map[offset / ID_PER_SC];
  33. unsigned int shift = (offset % ID_PER_SC) * ID_SHIFT;
  34. unsigned int new_ids, old_ids = atomic_read(&sc->ids);
  35. do {
  36. old_id = (old_ids >> shift) & ID_MASK;
  37. new_ids = (old_ids & ~(ID_MASK << shift));
  38. new_ids |= ((unsigned int)new_id) << shift;
  39. } while (!atomic_try_cmpxchg(&sc->ids, &old_ids, new_ids));
  40. return old_id;
  41. }
  42. /**
  43. * swap_cgroup_record - record mem_cgroup for a set of swap entries.
  44. * These entries must belong to one single folio, and that folio
  45. * must be being charged for swap space (swap out), and these
  46. * entries must not have been charged
  47. *
  48. * @folio: the folio that the swap entry belongs to
  49. * @id: mem_cgroup ID to be recorded
  50. * @ent: the first swap entry to be recorded
  51. */
  52. void swap_cgroup_record(struct folio *folio, unsigned short id,
  53. swp_entry_t ent)
  54. {
  55. unsigned int nr_ents = folio_nr_pages(folio);
  56. struct swap_cgroup *map;
  57. pgoff_t offset, end;
  58. unsigned short old;
  59. offset = swp_offset(ent);
  60. end = offset + nr_ents;
  61. map = swap_cgroup_ctrl[swp_type(ent)].map;
  62. do {
  63. old = __swap_cgroup_id_xchg(map, offset, id);
  64. VM_BUG_ON(old);
  65. } while (++offset != end);
  66. }
  67. /**
  68. * swap_cgroup_clear - clear mem_cgroup for a set of swap entries.
  69. * These entries must be being uncharged from swap. They either
  70. * belongs to one single folio in the swap cache (swap in for
  71. * cgroup v1), or no longer have any users (slot freeing).
  72. *
  73. * @ent: the first swap entry to be recorded into
  74. * @nr_ents: number of swap entries to be recorded
  75. *
  76. * Returns the existing old value.
  77. */
  78. unsigned short swap_cgroup_clear(swp_entry_t ent, unsigned int nr_ents)
  79. {
  80. pgoff_t offset, end;
  81. struct swap_cgroup *map;
  82. unsigned short old, iter = 0;
  83. offset = swp_offset(ent);
  84. end = offset + nr_ents;
  85. map = swap_cgroup_ctrl[swp_type(ent)].map;
  86. do {
  87. old = __swap_cgroup_id_xchg(map, offset, 0);
  88. if (!iter)
  89. iter = old;
  90. VM_BUG_ON(iter != old);
  91. } while (++offset != end);
  92. return old;
  93. }
  94. /**
  95. * lookup_swap_cgroup_id - lookup mem_cgroup id tied to swap entry
  96. * @ent: swap entry to be looked up.
  97. *
  98. * Returns ID of mem_cgroup at success. 0 at failure. (0 is invalid ID)
  99. */
  100. unsigned short lookup_swap_cgroup_id(swp_entry_t ent)
  101. {
  102. struct swap_cgroup_ctrl *ctrl;
  103. if (mem_cgroup_disabled())
  104. return 0;
  105. ctrl = &swap_cgroup_ctrl[swp_type(ent)];
  106. return __swap_cgroup_id_lookup(ctrl->map, swp_offset(ent));
  107. }
  108. int swap_cgroup_swapon(int type, unsigned long max_pages)
  109. {
  110. struct swap_cgroup *map;
  111. struct swap_cgroup_ctrl *ctrl;
  112. if (mem_cgroup_disabled())
  113. return 0;
  114. BUILD_BUG_ON(sizeof(unsigned short) * ID_PER_SC !=
  115. sizeof(struct swap_cgroup));
  116. map = vzalloc(DIV_ROUND_UP(max_pages, ID_PER_SC) *
  117. sizeof(struct swap_cgroup));
  118. if (!map)
  119. goto nomem;
  120. ctrl = &swap_cgroup_ctrl[type];
  121. mutex_lock(&swap_cgroup_mutex);
  122. ctrl->map = map;
  123. mutex_unlock(&swap_cgroup_mutex);
  124. return 0;
  125. nomem:
  126. pr_info("couldn't allocate enough memory for swap_cgroup\n");
  127. pr_info("swap_cgroup can be disabled by swapaccount=0 boot option\n");
  128. return -ENOMEM;
  129. }
  130. void swap_cgroup_swapoff(int type)
  131. {
  132. struct swap_cgroup *map;
  133. struct swap_cgroup_ctrl *ctrl;
  134. if (mem_cgroup_disabled())
  135. return;
  136. mutex_lock(&swap_cgroup_mutex);
  137. ctrl = &swap_cgroup_ctrl[type];
  138. map = ctrl->map;
  139. ctrl->map = NULL;
  140. mutex_unlock(&swap_cgroup_mutex);
  141. vfree(map);
  142. }