[Devel] [PATCH RHEL8 COMMIT] mm: remove the tswap
Konstantin Khorenko
khorenko at virtuozzo.com
Thu Apr 2 16:51:27 MSK 2020
The commit is pushed to "branch-rh8-4.18.0-80.1.2.vz8.3.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-80.1.2.vz8.3.4
------>
commit deb404e24152a4cbfc27d22eeda84165a24ddd72
Author: Andrey Ryabinin <aryabinin at virtuozzo.com>
Date: Thu Apr 2 16:51:26 2020 +0300
mm: remove the tswap
The idea of keeping containers swap in the memory, like tswap does,
doesn't make much sense, since it's better to give more memory to a container.
Hence, remove the tswap.
https://jira.sw.ru/browse/PSBM-102721
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
fs/proc/meminfo.c | 8 -
mm/Kconfig | 10 --
mm/Makefile | 1 -
mm/tswap.c | 432 ------------------------------------------------------
4 files changed, 451 deletions(-)
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index 87e95ab17122..eff94c92d824 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -36,11 +36,6 @@ extern unsigned long get_nr_tcache_pages(void);
#else
static inline unsigned long get_nr_tcache_pages(void) { return 0; }
#endif
-#ifdef CONFIG_TSWAP
-extern unsigned long get_nr_tswap_pages(void);
-#else
-static inline unsigned long get_nr_tswap_pages(void) { return 0; }
-#endif
extern void tree_stat(struct mem_cgroup *memcg, unsigned long *stat);
@@ -253,9 +248,6 @@ static int meminfo_proc_show_ve(struct seq_file *m, void *v,
if (IS_ENABLED(CONFIG_TCACHE))
show_val_kb(m, "Tcache: ", get_nr_tcache_pages());
- if (IS_ENABLED(CONFIG_TSWAP))
- show_val_kb(m, "Tswap: ", get_nr_tswap_pages());
-
#ifdef CONFIG_CMA
show_val_kb(m, "CmaTotal: ", totalcma_pages);
show_val_kb(m, "CmaFree: ",
diff --git a/mm/Kconfig b/mm/Kconfig
index 291bb5328c32..088bc901766f 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -538,16 +538,6 @@ config TCACHE
only worth enabling if used along with memory cgroups in order to
cache pages which were reclaimed on local pressure.
-config TSWAP
- bool "Transcendent swap cache"
- depends on FRONTSWAP
- default n
- help
- Transcendent swap cache is a simple backend for frontswap, which
- stores reclaimed pages in memory without any modifications. It is
- only worth enabling if used along with memory cgroups in order to
- cache pages which were reclaimed on local pressure.
-
config ZSWAP
bool "Compressed cache for swap pages (EXPERIMENTAL)"
depends on FRONTSWAP && CRYPTO=y
diff --git a/mm/Makefile b/mm/Makefile
index b3addd5b9fcb..6a75afd2a1d8 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -64,7 +64,6 @@ obj-$(CONFIG_SPARSEMEM) += sparse.o
obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
obj-$(CONFIG_SLOB) += slob.o
obj-$(CONFIG_TCACHE) += tcache.o
-obj-$(CONFIG_TSWAP) += tswap.o
obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
obj-$(CONFIG_KSM) += ksm.o
obj-$(CONFIG_PAGE_POISONING) += page_poison.o
diff --git a/mm/tswap.c b/mm/tswap.c
deleted file mode 100644
index 0fee087c2971..000000000000
--- a/mm/tswap.c
+++ /dev/null
@@ -1,432 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/gfp.h>
-#include <linux/slab.h>
-#include <linux/highmem.h>
-#include <linux/atomic.h>
-#include <linux/spinlock.h>
-#include <linux/radix-tree.h>
-#include <linux/list.h>
-#include <linux/swap.h>
-#include <linux/swapops.h>
-#include <linux/pagemap.h>
-#include <linux/shrinker.h>
-#include <linux/frontswap.h>
-
-#define TSWAP_GFP_MASK (GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN)
-
-static RADIX_TREE(tswap_page_tree, GFP_ATOMIC | __GFP_NOWARN);
-static DEFINE_SPINLOCK(tswap_lock);
-
-struct tswap_lru {
- struct list_head list;
- unsigned long nr_items;
-} ____cacheline_aligned_in_smp;
-
-static struct tswap_lru *tswap_lru_node;
-
-/* Enable/disable tswap backend (set at boot time) */
-static bool tswap_enabled __read_mostly = true;
-module_param_named(enabled, tswap_enabled, bool, 0444);
-
-/* Enable/disable populating the cache */
-static bool tswap_active __read_mostly = true;
-module_param_named(active, tswap_active, bool, 0644);
-
-/* Total number of pages cached */
-static unsigned long tswap_nr_pages;
-module_param_named(nr_pages, tswap_nr_pages, ulong, 0444);
-
-/* Enable/disable zero pages */
-static bool tswap_check_zero __read_mostly = true;
-module_param_named(check_zero, tswap_check_zero, bool, 0644);
-
-unsigned long get_nr_tswap_pages(void)
-{
- return tswap_nr_pages;
-}
-
-static void tswap_lru_add(struct page *page)
-{
- struct tswap_lru *lru = &tswap_lru_node[page_to_nid(page)];
-
- if (page != ZERO_PAGE(0)) {
- list_add_tail(&page->lru, &lru->list);
- lru->nr_items++;
- }
-}
-
-static void tswap_lru_del(struct page *page)
-{
- struct tswap_lru *lru = &tswap_lru_node[page_to_nid(page)];
-
- if (page != ZERO_PAGE(0)) {
- list_del(&page->lru);
- lru->nr_items--;
- }
-}
-
-static struct page *tswap_lookup_page(swp_entry_t entry)
-{
- struct page *page;
-
- spin_lock(&tswap_lock);
- page = radix_tree_lookup(&tswap_page_tree, entry.val);
- spin_unlock(&tswap_lock);
- BUG_ON(page && page != ZERO_PAGE(0) && page_private(page) != entry.val);
- return page;
-}
-
-static int tswap_insert_page(swp_entry_t entry, struct page *page)
-{
- int err;
-
- err = radix_tree_preload(TSWAP_GFP_MASK);
- if (err)
- return err;
-
- if (page != ZERO_PAGE(0))
- set_page_private(page, entry.val);
- spin_lock(&tswap_lock);
- err = radix_tree_insert(&tswap_page_tree, entry.val, page);
- if (!err) {
- tswap_lru_add(page);
- tswap_nr_pages++;
- }
- spin_unlock(&tswap_lock);
-
- radix_tree_preload_end();
- return err;
-}
-
-static struct page *tswap_delete_page(swp_entry_t entry, struct page *expected)
-{
- struct page *page;
-
- spin_lock(&tswap_lock);
- page = radix_tree_delete_item(&tswap_page_tree, entry.val, expected);
- if (page) {
- tswap_lru_del(page);
- tswap_nr_pages--;
- }
- spin_unlock(&tswap_lock);
- if (page) {
- BUG_ON(expected && page != expected);
- BUG_ON(page_private(page) != entry.val && page != ZERO_PAGE(0));
- }
- return page;
-}
-
-static unsigned long tswap_shrink_count(struct shrinker *shrink,
- struct shrink_control *sc)
-{
- return tswap_lru_node[sc->nid].nr_items;
-}
-
-static int tswap_evict_page(struct page *page)
-{
- struct address_space *swapper_space;
- struct page *found_page;
- swp_entry_t entry;
- int err;
-
- BUG_ON(!PageLocked(page));
-
- entry.val = page_private(page);
- swapper_space = swap_address_space(entry);
-retry:
- err = -EEXIST;
- found_page = find_get_page(swapper_space, entry.val);
- if (found_page) {
- /*
- * There is already a swap cache page at the given offset. If
- * the page is uptodate, we can safely free the frontswap page,
- * marking the swapcache page dirty. Otherwise, the frontswap
- * page is about to be loaded and cannot be released.
- */
- err = -EBUSY;
- if (!trylock_page(found_page)) {
- put_page(found_page);
- goto out;
- }
- /* recheck that the page is still in the swap cache */
- if (!PageSwapCache(found_page) ||
- page_private(found_page) != entry.val) {
- unlock_page(found_page);
- put_page(found_page);
- goto retry;
- }
- if (PageUptodate(found_page)) {
- /*
- * Since we are holding the swap cache page lock, no
- * frontswap callbacks are allowed now. However, the
- * frontswap page could have been invalidated before we
- * took the lock, in which case we have nothing to do.
- */
- err = -ENOENT;
- if (tswap_delete_page(entry, page)) {
- SetPageDirty(found_page);
- put_page(page);
- err = 0;
- }
- }
- unlock_page(found_page);
- put_page(found_page);
- goto out;
- }
-
- err = swapcache_prepare(entry);
- if (err == -EEXIST) {
- cond_resched();
- goto retry;
- }
- if (err)
- /* the swap entry has been freed, and therefore the page must
- * have been invalidated */
- goto out;
-
- /*
- * From now on, no frontswap callbacks can be called on the swap entry,
- * because we hold its swap cache reference.
- */
-
- err = -ENOENT;
- if (tswap_lookup_page(entry) != page)
- /* the page could have been removed from tswap before we
- * prepared swap cache */
- goto out_free_swapcache;
-
- SetPageSwapBacked(page);
- err = __add_to_swap_cache(page, entry);
- if (err) {
- ClearPageSwapBacked(page);
- /* __add_to_swap_cache clears page->private on failure */
- set_page_private(page, entry.val);
- /* __add_to_swap_cache does not return -EEXIST, so we can
- * safely clear SWAP_HAS_CACHE flag */
- goto out_free_swapcache;
- }
-
- /* the page is now in the swap cache, remove it from tswap */
- BUG_ON(!tswap_delete_page(entry, page));
- put_page(page);
-
- lru_cache_add_anon(page);
- SetPageUptodate(page);
- SetPageDirty(page);
- return 0;
-
-out_free_swapcache:
- put_swap_page(page, entry);
-out:
- return err;
-}
-
-static unsigned long tswap_shrink_scan(struct shrinker *shrink,
- struct shrink_control *sc)
-{
- struct tswap_lru *lru = &tswap_lru_node[sc->nid];
- unsigned long nr_reclaimed = 0;
-
- spin_lock(&tswap_lock);
- while (sc->nr_to_scan-- > 0) {
- struct page *page;
-
- if (!lru->nr_items)
- break;
-
- page = list_first_entry(&lru->list, struct page, lru);
- /* lock the page to avoid interference with
- * other reclaiming threads */
- if (!trylock_page(page)) {
- list_move_tail(&page->lru, &lru->list);
- cond_resched_lock(&tswap_lock);
- continue;
- }
- get_page(page);
- spin_unlock(&tswap_lock);
-
- if (tswap_evict_page(page) == 0)
- nr_reclaimed++;
-
- unlock_page(page);
- put_page(page);
-
- cond_resched();
- spin_lock(&tswap_lock);
- }
- spin_unlock(&tswap_lock);
-
- return nr_reclaimed;
-}
-
-static struct shrinker tswap_shrinker = {
- .count_objects = tswap_shrink_count,
- .scan_objects = tswap_shrink_scan,
- .seeks = 1,
- .flags = SHRINKER_NUMA_AWARE,
-};
-
-static void tswap_frontswap_init(unsigned type)
-{
- /*
- * We maintain the single page tree for all swap types, so nothing to
- * do here.
- */
-}
-
-static bool is_zero_filled_page(struct page *page)
-{
- bool zero_filled = true;
- unsigned long *v;
- int i;
-
- if (!tswap_check_zero)
- return false;
-
- v = kmap_atomic(page);
- for (i = 0; i < PAGE_SIZE / sizeof(*v); i++) {
- if (v[i] != 0) {
- zero_filled = false;
- break;
- }
- }
- kunmap_atomic(v);
- return zero_filled;
-}
-
-static int tswap_frontswap_store(unsigned type, pgoff_t offset,
- struct page *page)
-{
- swp_entry_t entry = swp_entry(type, offset);
- int zero_filled = -1, err = 0;
- struct page *cache_page;
-
- if (!tswap_active)
- return -1;
-
- cache_page = tswap_lookup_page(entry);
- if (cache_page) {
- zero_filled = is_zero_filled_page(page);
- /* If type of page has not changed, just reuse it */
- if (zero_filled == (cache_page == ZERO_PAGE(0)))
- goto copy;
- tswap_delete_page(entry, NULL);
- put_page(cache_page);
- }
-
- if (!(current->flags & PF_MEMCG_RECLAIM))
- return -1;
-
- if (zero_filled == -1)
- zero_filled = is_zero_filled_page(page);
-
- if (!zero_filled) {
- cache_page = alloc_page(TSWAP_GFP_MASK | __GFP_HIGHMEM);
- if (!cache_page)
- return -1;
- } else {
- cache_page = ZERO_PAGE(0);
- get_page(cache_page);
- }
-
- err = tswap_insert_page(entry, cache_page);
- if (err) {
- /*
- * Frontswap stores proceed under the page lock, so this can
- * only fail with ENOMEM.
- */
- BUG_ON(err == -EEXIST);
- put_page(cache_page);
- return -1;
- }
-copy:
- if (cache_page != ZERO_PAGE(0))
- copy_highpage(cache_page, page);
- return 0;
-}
-
-static int tswap_frontswap_load(unsigned type, pgoff_t offset,
- struct page *page)
-{
- struct page *cache_page;
-
- cache_page = tswap_delete_page(swp_entry(type, offset), NULL);
- if (!cache_page)
- return -1;
-
- copy_highpage(page, cache_page);
- put_page(cache_page);
- return 0;
-}
-
-static void tswap_frontswap_invalidate_page(unsigned type, pgoff_t offset)
-{
- struct page *cache_page;
-
- cache_page = tswap_delete_page(swp_entry(type, offset), NULL);
- if (cache_page)
- put_page(cache_page);
-}
-
-static void tswap_frontswap_invalidate_area(unsigned type)
-{
- /*
- * This function is called on swapoff after all swap entries of the
- * given type has been freed and therefore all frontswap pages has been
- * invalidated, so nothing to do here.
- */
-}
-
-static struct frontswap_ops tswap_frontswap_ops = {
- .init = tswap_frontswap_init,
- .store = tswap_frontswap_store,
- .load = tswap_frontswap_load,
- .invalidate_page = tswap_frontswap_invalidate_page,
- .invalidate_area = tswap_frontswap_invalidate_area,
-};
-
-static int __init tswap_lru_init(void)
-{
- int i;
-
- tswap_lru_node = kcalloc(nr_node_ids, sizeof(*tswap_lru_node),
- GFP_KERNEL);
- if (!tswap_lru_node)
- return -ENOMEM;
-
- for (i = 0; i < nr_node_ids; i++)
- INIT_LIST_HEAD(&tswap_lru_node[i].list);
- return 0;
-}
-
-static int __init tswap_init(void)
-{
- int err;
-
- if (!tswap_enabled)
- return 0;
-
- err = tswap_lru_init();
- if (err)
- goto out_fail;
-
- err = register_shrinker(&tswap_shrinker);
- if (err)
- goto out_free_lru;
-
- frontswap_tmem_exclusive_gets(true);
- frontswap_register_ops(&tswap_frontswap_ops);
-
- return 0;
-
-out_free_lru:
- kfree(tswap_lru_node);
-out_fail:
- return err;
-}
-module_init(tswap_init);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Transcendent swap cache");
More information about the Devel
mailing list