mm/mglru: fix underprotected page cache
[platform/kernel/linux-starfive.git] / include / linux / mm_inline.h
index 8148b30..96b1c15 100644 (file)
@@ -231,22 +231,27 @@ static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio,
        if (folio_test_unevictable(folio) || !lrugen->enabled)
                return false;
        /*
-        * There are three common cases for this page:
-        * 1. If it's hot, e.g., freshly faulted in or previously hot and
-        *    migrated, add it to the youngest generation.
-        * 2. If it's cold but can't be evicted immediately, i.e., an anon page
-        *    not in swapcache or a dirty page pending writeback, add it to the
-        *    second oldest generation.
-        * 3. Everything else (clean, cold) is added to the oldest generation.
+        * There are four common cases for this page:
+        * 1. If it's hot, i.e., freshly faulted in, add it to the youngest
+        *    generation, and it's protected over the rest below.
+        * 2. If it can't be evicted immediately, i.e., a dirty page pending
+        *    writeback, add it to the second youngest generation.
+        * 3. If it should be evicted first, e.g., cold and clean from
+        *    folio_rotate_reclaimable(), add it to the oldest generation.
+        * 4. Everything else falls between 2 & 3 above and is added to the
+        *    second oldest generation if it's considered inactive, or the
+        *    oldest generation otherwise. See lru_gen_is_active().
         */
        if (folio_test_active(folio))
                seq = lrugen->max_seq;
        else if ((type == LRU_GEN_ANON && !folio_test_swapcache(folio)) ||
                 (folio_test_reclaim(folio) &&
                  (folio_test_dirty(folio) || folio_test_writeback(folio))))
-               seq = lrugen->min_seq[type] + 1;
-       else
+               seq = lrugen->max_seq - 1;
+       else if (reclaiming || lrugen->min_seq[type] + MIN_NR_GENS >= lrugen->max_seq)
                seq = lrugen->min_seq[type];
+       else
+               seq = lrugen->min_seq[type] + 1;
 
        gen = lru_gen_from_seq(seq);
        flags = (gen + 1UL) << LRU_GEN_PGOFF;