020-v6.3-27-mm-multi-gen-LRU-clarify-scan_control-flags.patch 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. From 93147736b5b3a21bea24313bfc7a696829932009 Mon Sep 17 00:00:00 2001
  2. From: Yu Zhao <[email protected]>
  3. Date: Wed, 21 Dec 2022 21:19:05 -0700
  4. Subject: [PATCH 27/29] mm: multi-gen LRU: clarify scan_control flags
  5. Among the flags in scan_control:
  6. 1. sc->may_swap, which indicates swap constraint due to memsw.max, is
  7. supported as usual.
  8. 2. sc->proactive, which indicates reclaim by memory.reclaim, may not
  9. opportunistically skip the aging path, since it is considered less
  10. latency sensitive.
  11. 3. !(sc->gfp_mask & __GFP_IO), which indicates IO constraint, lowers
  12. swappiness to prioritize file LRU, since clean file folios are more
  13. likely to exist.
  14. 4. sc->may_writefolio and sc->may_unmap, which indicates opportunistic
  15. reclaim, are rejected, since unmapped clean folios are already
  16. prioritized. Scanning for more of them is likely futile and can
  17. cause high reclaim latency when there is a large number of memcgs.
  18. The rest are handled by the existing code.
  19. Link: https://lkml.kernel.org/r/[email protected]
  20. Signed-off-by: Yu Zhao <[email protected]>
  21. Cc: Johannes Weiner <[email protected]>
  22. Cc: Jonathan Corbet <[email protected]>
  23. Cc: Michael Larabel <[email protected]>
  24. Cc: Michal Hocko <[email protected]>
  25. Cc: Mike Rapoport <[email protected]>
  26. Cc: Roman Gushchin <[email protected]>
  27. Cc: Suren Baghdasaryan <[email protected]>
  28. Signed-off-by: Andrew Morton <[email protected]>
  29. ---
  30. mm/vmscan.c | 55 +++++++++++++++++++++++++++--------------------------
  31. 1 file changed, 28 insertions(+), 27 deletions(-)
  32. --- a/mm/vmscan.c
  33. +++ b/mm/vmscan.c
  34. @@ -2905,6 +2905,9 @@ static int get_swappiness(struct lruvec
  35. struct mem_cgroup *memcg = lruvec_memcg(lruvec);
  36. struct pglist_data *pgdat = lruvec_pgdat(lruvec);
  37. + if (!sc->may_swap)
  38. + return 0;
  39. +
  40. if (!can_demote(pgdat->node_id, sc) &&
  41. mem_cgroup_get_nr_swap_folios(memcg) < MIN_LRU_BATCH)
  42. return 0;
  43. @@ -3952,7 +3955,7 @@ static void walk_mm(struct lruvec *lruve
  44. } while (err == -EAGAIN);
  45. }
  46. -static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat)
  47. +static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat, bool force_alloc)
  48. {
  49. struct lru_gen_mm_walk *walk = current->reclaim_state->mm_walk;
  50. @@ -3960,7 +3963,7 @@ static struct lru_gen_mm_walk *set_mm_wa
  51. VM_WARN_ON_ONCE(walk);
  52. walk = &pgdat->mm_walk;
  53. - } else if (!pgdat && !walk) {
  54. + } else if (!walk && force_alloc) {
  55. VM_WARN_ON_ONCE(current_is_kswapd());
  56. walk = kzalloc(sizeof(*walk), __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN);
  57. @@ -4146,7 +4149,7 @@ static bool try_to_inc_max_seq(struct lr
  58. goto done;
  59. }
  60. - walk = set_mm_walk(NULL);
  61. + walk = set_mm_walk(NULL, true);
  62. if (!walk) {
  63. success = iterate_mm_list_nowalk(lruvec, max_seq);
  64. goto done;
  65. @@ -4215,8 +4218,6 @@ static bool lruvec_is_reclaimable(struct
  66. struct mem_cgroup *memcg = lruvec_memcg(lruvec);
  67. DEFINE_MIN_SEQ(lruvec);
  68. - VM_WARN_ON_ONCE(sc->memcg_low_reclaim);
  69. -
  70. /* see the comment on lru_gen_folio */
  71. gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]);
  72. birth = READ_ONCE(lruvec->lrugen.timestamps[gen]);
  73. @@ -4472,12 +4473,8 @@ static bool isolate_folio(struct lruvec *
  74. {
  75. bool success;
  76. - /* unmapping inhibited */
  77. - if (!sc->may_unmap && folio_mapped(folio))
  78. - return false;
  79. -
  80. /* swapping inhibited */
  81. - if (!(sc->may_writepage && (sc->gfp_mask & __GFP_IO)) &&
  82. + if (!(sc->gfp_mask & __GFP_IO) &&
  83. (folio_test_dirty(folio) ||
  84. (folio_test_anon(folio) && !folio_test_swapcache(folio))))
  85. return false;
  86. @@ -4574,9 +4571,8 @@ static int scan_folios(struct lruvec *lru
  87. __count_vm_events(PGSCAN_ANON + type, isolated);
  88. /*
  89. - * There might not be eligible pages due to reclaim_idx, may_unmap and
  90. - * may_writepage. Check the remaining to prevent livelock if it's not
  91. - * making progress.
  92. + * There might not be eligible pages due to reclaim_idx. Check the
  93. + * remaining to prevent livelock if it's not making progress.
  94. */
  95. return isolated || !remaining ? scanned : 0;
  96. }
  97. @@ -4836,8 +4832,7 @@ static long get_nr_to_scan(struct lruvec
  98. struct mem_cgroup *memcg = lruvec_memcg(lruvec);
  99. DEFINE_MAX_SEQ(lruvec);
  100. - if (mem_cgroup_below_min(memcg) ||
  101. - (mem_cgroup_below_low(memcg) && !sc->memcg_low_reclaim))
  102. + if (mem_cgroup_below_min(memcg))
  103. return 0;
  104. if (!should_run_aging(lruvec, max_seq, sc, can_swap, &nr_to_scan))
  105. @@ -4865,17 +4860,14 @@ static bool try_to_shrink_lruvec(struct
  106. long nr_to_scan;
  107. unsigned long scanned = 0;
  108. unsigned long nr_to_reclaim = get_nr_to_reclaim(sc);
  109. + int swappiness = get_swappiness(lruvec, sc);
  110. +
  111. + /* clean file folios are more likely to exist */
  112. + if (swappiness && !(sc->gfp_mask & __GFP_IO))
  113. + swappiness = 1;
  114. while (true) {
  115. int delta;
  116. - int swappiness;
  117. -
  118. - if (sc->may_swap)
  119. - swappiness = get_swappiness(lruvec, sc);
  120. - else if (!cgroup_reclaim(sc) && get_swappiness(lruvec, sc))
  121. - swappiness = 1;
  122. - else
  123. - swappiness = 0;
  124. nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness);
  125. if (nr_to_scan <= 0)
  126. @@ -5005,12 +4997,13 @@ static void lru_gen_shrink_lruvec(struct
  127. struct blk_plug plug;
  128. VM_WARN_ON_ONCE(global_reclaim(sc));
  129. + VM_WARN_ON_ONCE(!sc->may_writepage || !sc->may_unmap);
  130. lru_add_drain();
  131. blk_start_plug(&plug);
  132. - set_mm_walk(lruvec_pgdat(lruvec));
  133. + set_mm_walk(NULL, sc->proactive);
  134. if (try_to_shrink_lruvec(lruvec, sc))
  135. lru_gen_rotate_memcg(lruvec, MEMCG_LRU_YOUNG);
  136. @@ -5066,11 +5059,19 @@ static void lru_gen_shrink_node(struct p
  137. VM_WARN_ON_ONCE(!global_reclaim(sc));
  138. + /*
  139. + * Unmapped clean folios are already prioritized. Scanning for more of
  140. + * them is likely futile and can cause high reclaim latency when there
  141. + * is a large number of memcgs.
  142. + */
  143. + if (!sc->may_writepage || !sc->may_unmap)
  144. + goto done;
  145. +
  146. lru_add_drain();
  147. blk_start_plug(&plug);
  148. - set_mm_walk(pgdat);
  149. + set_mm_walk(NULL, sc->proactive);
  150. set_initial_priority(pgdat, sc);
  151. @@ -5088,7 +5089,7 @@ static void lru_gen_shrink_node(struct p
  152. clear_mm_walk();
  153. blk_finish_plug(&plug);
  154. -
  155. +done:
  156. /* kswapd should never fail */
  157. pgdat->kswapd_failures = 0;
  158. }
  159. @@ -5656,7 +5657,7 @@ static ssize_t lru_gen_seq_write(struct
  160. set_task_reclaim_state(current, &sc.reclaim_state);
  161. flags = memalloc_noreclaim_save();
  162. blk_start_plug(&plug);
  163. - if (!set_mm_walk(NULL)) {
  164. + if (!set_mm_walk(NULL, true)) {
  165. err = -ENOMEM;
  166. goto done;
  167. }