Commit 42c06a0e authored by Johannes Weiner's avatar Johannes Weiner Committed by Andrew Morton

mm: kill frontswap

The only user of frontswap is zswap, and has been for a long time.  Have
swap call into zswap directly and remove the indirection.

[hannes@cmpxchg.org: remove obsolete comment, per Yosry]
  Link: https://lkml.kernel.org/r/20230719142832.GA932528@cmpxchg.org
[fengwei.yin@intel.com: don't warn if none swapcache folio is passed to zswap_load]
  Link: https://lkml.kernel.org/r/20230810095652.3905184-1-fengwei.yin@intel.com
Link: https://lkml.kernel.org/r/20230717160227.GA867137@cmpxchg.orgSigned-off-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
Signed-off-by: default avatarYin Fengwei <fengwei.yin@intel.com>
Acked-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Acked-by: default avatarNhat Pham <nphamcs@gmail.com>
Acked-by: default avatarYosry Ahmed <yosryahmed@google.com>
Acked-by: default avatarChristoph Hellwig <hch@lst.de>
Cc: Domenico Cerasuolo <cerasuolodomenico@gmail.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Vitaly Wool <vitaly.wool@konsulko.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent b8cf32dc
...@@ -49,7 +49,7 @@ compressed pool. ...@@ -49,7 +49,7 @@ compressed pool.
Design Design
====== ======
Zswap receives pages for compression through the Frontswap API and is able to Zswap receives pages for compression from the swap subsystem and is able to
evict pages from its own compressed pool on an LRU basis and write them back to evict pages from its own compressed pool on an LRU basis and write them back to
the backing swap device in the case that the compressed pool is full. the backing swap device in the case that the compressed pool is full.
...@@ -70,19 +70,19 @@ means the compression ratio will always be 2:1 or worse (because of half-full ...@@ -70,19 +70,19 @@ means the compression ratio will always be 2:1 or worse (because of half-full
zbud pages). The zsmalloc type zpool has a more complex compressed page zbud pages). The zsmalloc type zpool has a more complex compressed page
storage method, and it can achieve greater storage densities. storage method, and it can achieve greater storage densities.
When a swap page is passed from frontswap to zswap, zswap maintains a mapping When a swap page is passed from swapout to zswap, zswap maintains a mapping
of the swap entry, a combination of the swap type and swap offset, to the zpool of the swap entry, a combination of the swap type and swap offset, to the zpool
handle that references that compressed swap page. This mapping is achieved handle that references that compressed swap page. This mapping is achieved
with a red-black tree per swap type. The swap offset is the search key for the with a red-black tree per swap type. The swap offset is the search key for the
tree nodes. tree nodes.
During a page fault on a PTE that is a swap entry, frontswap calls the zswap During a page fault on a PTE that is a swap entry, the swapin code calls the
load function to decompress the page into the page allocated by the page fault zswap load function to decompress the page into the page allocated by the page
handler. fault handler.
Once there are no PTEs referencing a swap page stored in zswap (i.e. the count Once there are no PTEs referencing a swap page stored in zswap (i.e. the count
in the swap_map goes to 0) the swap code calls the zswap invalidate function, in the swap_map goes to 0) the swap code calls the zswap invalidate function
via frontswap, to free the compressed entry. to free the compressed entry.
Zswap seeks to be simple in its policies. Sysfs attributes allow for one user Zswap seeks to be simple in its policies. Sysfs attributes allow for one user
controlled policy: controlled policy:
......
This diff is collapsed.
...@@ -44,7 +44,6 @@ above structured documentation, or deleted if it has served its purpose. ...@@ -44,7 +44,6 @@ above structured documentation, or deleted if it has served its purpose.
balance balance
damon/index damon/index
free_page_reporting free_page_reporting
frontswap
hmm hmm
hwpoison hwpoison
hugetlbfs_reserv hugetlbfs_reserv
......
This diff is collapsed.
...@@ -42,7 +42,6 @@ Linux内存管理文档 ...@@ -42,7 +42,6 @@ Linux内存管理文档
damon/index damon/index
free_page_reporting free_page_reporting
ksm ksm
frontswap
hmm hmm
hwpoison hwpoison
hugetlbfs_reserv hugetlbfs_reserv
......
...@@ -8404,13 +8404,6 @@ F: Documentation/power/freezing-of-tasks.rst ...@@ -8404,13 +8404,6 @@ F: Documentation/power/freezing-of-tasks.rst
F: include/linux/freezer.h F: include/linux/freezer.h
F: kernel/freezer.c F: kernel/freezer.c
FRONTSWAP API
M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
L: linux-kernel@vger.kernel.org
S: Maintained
F: include/linux/frontswap.h
F: mm/frontswap.c
FS-CACHE: LOCAL CACHING FOR NETWORK FILESYSTEMS FS-CACHE: LOCAL CACHING FOR NETWORK FILESYSTEMS
M: David Howells <dhowells@redhat.com> M: David Howells <dhowells@redhat.com>
L: linux-cachefs@redhat.com (moderated for non-subscribers) L: linux-cachefs@redhat.com (moderated for non-subscribers)
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#ifdef CONFIG_CMA #ifdef CONFIG_CMA
#include <linux/cma.h> #include <linux/cma.h>
#endif #endif
#include <linux/zswap.h>
#include <asm/page.h> #include <asm/page.h>
#include "internal.h" #include "internal.h"
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_FRONTSWAP_H
#define _LINUX_FRONTSWAP_H
#include <linux/swap.h>
#include <linux/mm.h>
#include <linux/bitops.h>
#include <linux/jump_label.h>
struct frontswap_ops {
void (*init)(unsigned); /* this swap type was just swapon'ed */
int (*store)(unsigned, pgoff_t, struct page *); /* store a page */
int (*load)(unsigned, pgoff_t, struct page *, bool *); /* load a page */
void (*invalidate_page)(unsigned, pgoff_t); /* page no longer needed */
void (*invalidate_area)(unsigned); /* swap type just swapoff'ed */
};
int frontswap_register_ops(const struct frontswap_ops *ops);
extern void frontswap_init(unsigned type, unsigned long *map);
extern int __frontswap_store(struct page *page);
extern int __frontswap_load(struct page *page);
extern void __frontswap_invalidate_page(unsigned, pgoff_t);
extern void __frontswap_invalidate_area(unsigned);
#ifdef CONFIG_FRONTSWAP
extern struct static_key_false frontswap_enabled_key;
static inline bool frontswap_enabled(void)
{
return static_branch_unlikely(&frontswap_enabled_key);
}
static inline void frontswap_map_set(struct swap_info_struct *p,
unsigned long *map)
{
p->frontswap_map = map;
}
static inline unsigned long *frontswap_map_get(struct swap_info_struct *p)
{
return p->frontswap_map;
}
#else
/* all inline routines become no-ops and all externs are ignored */
static inline bool frontswap_enabled(void)
{
return false;
}
static inline void frontswap_map_set(struct swap_info_struct *p,
unsigned long *map)
{
}
static inline unsigned long *frontswap_map_get(struct swap_info_struct *p)
{
return NULL;
}
#endif
static inline int frontswap_store(struct page *page)
{
if (frontswap_enabled())
return __frontswap_store(page);
return -1;
}
static inline int frontswap_load(struct page *page)
{
if (frontswap_enabled())
return __frontswap_load(page);
return -1;
}
static inline void frontswap_invalidate_page(unsigned type, pgoff_t offset)
{
if (frontswap_enabled())
__frontswap_invalidate_page(type, offset);
}
static inline void frontswap_invalidate_area(unsigned type)
{
if (frontswap_enabled())
__frontswap_invalidate_area(type);
}
#endif /* _LINUX_FRONTSWAP_H */
...@@ -302,10 +302,6 @@ struct swap_info_struct { ...@@ -302,10 +302,6 @@ struct swap_info_struct {
struct file *swap_file; /* seldom referenced */ struct file *swap_file; /* seldom referenced */
unsigned int old_block_size; /* seldom referenced */ unsigned int old_block_size; /* seldom referenced */
struct completion comp; /* seldom referenced */ struct completion comp; /* seldom referenced */
#ifdef CONFIG_FRONTSWAP
unsigned long *frontswap_map; /* frontswap in-use, one bit per page */
atomic_t frontswap_pages; /* frontswap pages in-use counter */
#endif
spinlock_t lock; /* spinlock_t lock; /*
* protect map scan related fields like * protect map scan related fields like
* swap_map, lowest_bit, highest_bit, * swap_map, lowest_bit, highest_bit,
...@@ -630,11 +626,6 @@ static inline int mem_cgroup_swappiness(struct mem_cgroup *mem) ...@@ -630,11 +626,6 @@ static inline int mem_cgroup_swappiness(struct mem_cgroup *mem)
} }
#endif #endif
#ifdef CONFIG_ZSWAP
extern u64 zswap_pool_total_size;
extern atomic_t zswap_stored_pages;
#endif
#if defined(CONFIG_SWAP) && defined(CONFIG_MEMCG) && defined(CONFIG_BLK_CGROUP) #if defined(CONFIG_SWAP) && defined(CONFIG_MEMCG) && defined(CONFIG_BLK_CGROUP)
void __folio_throttle_swaprate(struct folio *folio, gfp_t gfp); void __folio_throttle_swaprate(struct folio *folio, gfp_t gfp);
static inline void folio_throttle_swaprate(struct folio *folio, gfp_t gfp) static inline void folio_throttle_swaprate(struct folio *folio, gfp_t gfp)
......
...@@ -2,11 +2,6 @@ ...@@ -2,11 +2,6 @@
#ifndef _LINUX_SWAPFILE_H #ifndef _LINUX_SWAPFILE_H
#define _LINUX_SWAPFILE_H #define _LINUX_SWAPFILE_H
/*
* these were static in swapfile.c but frontswap.c needs them and we don't
* want to expose them to the dozens of source files that include swap.h
*/
extern struct swap_info_struct *swap_info[];
extern unsigned long generic_max_swapfile_size(void); extern unsigned long generic_max_swapfile_size(void);
unsigned long arch_max_swapfile_size(void); unsigned long arch_max_swapfile_size(void);
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_ZSWAP_H
#define _LINUX_ZSWAP_H
#include <linux/types.h>
#include <linux/mm_types.h>
extern u64 zswap_pool_total_size;
extern atomic_t zswap_stored_pages;
#ifdef CONFIG_ZSWAP
bool zswap_store(struct page *page);
bool zswap_load(struct page *page);
void zswap_invalidate(int type, pgoff_t offset);
void zswap_swapon(int type);
void zswap_swapoff(int type);
#else
static inline bool zswap_store(struct page *page)
{
return false;
}
static inline bool zswap_load(struct page *page)
{
return false;
}
static inline void zswap_invalidate(int type, pgoff_t offset) {}
static inline void zswap_swapon(int type) {}
static inline void zswap_swapoff(int type) {}
#endif
#endif /* _LINUX_ZSWAP_H */
...@@ -25,7 +25,6 @@ menuconfig SWAP ...@@ -25,7 +25,6 @@ menuconfig SWAP
config ZSWAP config ZSWAP
bool "Compressed cache for swap pages" bool "Compressed cache for swap pages"
depends on SWAP depends on SWAP
select FRONTSWAP
select CRYPTO select CRYPTO
select ZPOOL select ZPOOL
help help
...@@ -873,9 +872,6 @@ config USE_PERCPU_NUMA_NODE_ID ...@@ -873,9 +872,6 @@ config USE_PERCPU_NUMA_NODE_ID
config HAVE_SETUP_PER_CPU_AREA config HAVE_SETUP_PER_CPU_AREA
bool bool
config FRONTSWAP
bool
config CMA config CMA
bool "Contiguous Memory Allocator" bool "Contiguous Memory Allocator"
depends on MMU depends on MMU
......
...@@ -72,7 +72,6 @@ ifdef CONFIG_MMU ...@@ -72,7 +72,6 @@ ifdef CONFIG_MMU
endif endif
obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o swap_slots.o obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o swap_slots.o
obj-$(CONFIG_FRONTSWAP) += frontswap.o
obj-$(CONFIG_ZSWAP) += zswap.o obj-$(CONFIG_ZSWAP) += zswap.o
obj-$(CONFIG_HAS_DMA) += dmapool.o obj-$(CONFIG_HAS_DMA) += dmapool.o
obj-$(CONFIG_HUGETLBFS) += hugetlb.o obj-$(CONFIG_HUGETLBFS) += hugetlb.o
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Frontswap frontend
*
* This code provides the generic "frontend" layer to call a matching
* "backend" driver implementation of frontswap. See
* Documentation/mm/frontswap.rst for more information.
*
* Copyright (C) 2009-2012 Oracle Corp. All rights reserved.
* Author: Dan Magenheimer
*/
#include <linux/mman.h>
#include <linux/swap.h>
#include <linux/swapops.h>
#include <linux/security.h>
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/frontswap.h>
#include <linux/swapfile.h>
DEFINE_STATIC_KEY_FALSE(frontswap_enabled_key);
/*
* frontswap_ops are added by frontswap_register_ops, and provide the
* frontswap "backend" implementation functions. Multiple implementations
* may be registered, but implementations can never deregister. This
* is a simple singly-linked list of all registered implementations.
*/
static const struct frontswap_ops *frontswap_ops __read_mostly;
#ifdef CONFIG_DEBUG_FS
/*
* Counters available via /sys/kernel/debug/frontswap (if debugfs is
* properly configured). These are for information only so are not protected
* against increment races.
*/
static u64 frontswap_loads;
static u64 frontswap_succ_stores;
static u64 frontswap_failed_stores;
static u64 frontswap_invalidates;
static inline void inc_frontswap_loads(void)
{
data_race(frontswap_loads++);
}
static inline void inc_frontswap_succ_stores(void)
{
data_race(frontswap_succ_stores++);
}
static inline void inc_frontswap_failed_stores(void)
{
data_race(frontswap_failed_stores++);
}
static inline void inc_frontswap_invalidates(void)
{
data_race(frontswap_invalidates++);
}
#else
static inline void inc_frontswap_loads(void) { }
static inline void inc_frontswap_succ_stores(void) { }
static inline void inc_frontswap_failed_stores(void) { }
static inline void inc_frontswap_invalidates(void) { }
#endif
/*
* Due to the asynchronous nature of the backends loading potentially
* _after_ the swap system has been activated, we have chokepoints
* on all frontswap functions to not call the backend until the backend
* has registered.
*
* This would not guards us against the user deciding to call swapoff right as
* we are calling the backend to initialize (so swapon is in action).
* Fortunately for us, the swapon_mutex has been taken by the callee so we are
* OK. The other scenario where calls to frontswap_store (called via
* swap_writepage) is racing with frontswap_invalidate_area (called via
* swapoff) is again guarded by the swap subsystem.
*
* While no backend is registered all calls to frontswap_[store|load|
* invalidate_area|invalidate_page] are ignored or fail.
*
* The time between the backend being registered and the swap file system
* calling the backend (via the frontswap_* functions) is indeterminate as
* frontswap_ops is not atomic_t (or a value guarded by a spinlock).
* That is OK as we are comfortable missing some of these calls to the newly
* registered backend.
*
* Obviously the opposite (unloading the backend) must be done after all
* the frontswap_[store|load|invalidate_area|invalidate_page] start
* ignoring or failing the requests. However, there is currently no way
* to unload a backend once it is registered.
*/
/*
* Register operations for frontswap
*/
int frontswap_register_ops(const struct frontswap_ops *ops)
{
if (frontswap_ops)
return -EINVAL;
frontswap_ops = ops;
static_branch_inc(&frontswap_enabled_key);
return 0;
}
/*
* Called when a swap device is swapon'd.
*/
void frontswap_init(unsigned type, unsigned long *map)
{
struct swap_info_struct *sis = swap_info[type];
VM_BUG_ON(sis == NULL);
/*
* p->frontswap is a bitmap that we MUST have to figure out which page
* has gone in frontswap. Without it there is no point of continuing.
*/
if (WARN_ON(!map))
return;
/*
* Irregardless of whether the frontswap backend has been loaded
* before this function or it will be later, we _MUST_ have the
* p->frontswap set to something valid to work properly.
*/
frontswap_map_set(sis, map);
if (!frontswap_enabled())
return;
frontswap_ops->init(type);
}
static bool __frontswap_test(struct swap_info_struct *sis,
pgoff_t offset)
{
if (sis->frontswap_map)
return test_bit(offset, sis->frontswap_map);
return false;
}
static inline void __frontswap_set(struct swap_info_struct *sis,
pgoff_t offset)
{
set_bit(offset, sis->frontswap_map);
atomic_inc(&sis->frontswap_pages);
}
static inline void __frontswap_clear(struct swap_info_struct *sis,
pgoff_t offset)
{
clear_bit(offset, sis->frontswap_map);
atomic_dec(&sis->frontswap_pages);
}
/*
* "Store" data from a page to frontswap and associate it with the page's
* swaptype and offset. Page must be locked and in the swap cache.
* If frontswap already contains a page with matching swaptype and
* offset, the frontswap implementation may either overwrite the data and
* return success or invalidate the page from frontswap and return failure.
*/
int __frontswap_store(struct page *page)
{
int ret = -1;
swp_entry_t entry = { .val = page_private(page), };
int type = swp_type(entry);
struct swap_info_struct *sis = swap_info[type];
pgoff_t offset = swp_offset(entry);
VM_BUG_ON(!frontswap_ops);
VM_BUG_ON(!PageLocked(page));
VM_BUG_ON(sis == NULL);
/*
* If a dup, we must remove the old page first; we can't leave the
* old page no matter if the store of the new page succeeds or fails,
* and we can't rely on the new page replacing the old page as we may
* not store to the same implementation that contains the old page.
*/
if (__frontswap_test(sis, offset)) {
__frontswap_clear(sis, offset);
frontswap_ops->invalidate_page(type, offset);
}
ret = frontswap_ops->store(type, offset, page);
if (ret == 0) {
__frontswap_set(sis, offset);
inc_frontswap_succ_stores();
} else {
inc_frontswap_failed_stores();
}
return ret;
}
/*
* "Get" data from frontswap associated with swaptype and offset that were
* specified when the data was put to frontswap and use it to fill the
* specified page with data. Page must be locked and in the swap cache.
*/
int __frontswap_load(struct page *page)
{
int ret = -1;
swp_entry_t entry = { .val = page_private(page), };
int type = swp_type(entry);
struct swap_info_struct *sis = swap_info[type];
pgoff_t offset = swp_offset(entry);
bool exclusive = false;
VM_BUG_ON(!frontswap_ops);
VM_BUG_ON(!PageLocked(page));
VM_BUG_ON(sis == NULL);
if (!__frontswap_test(sis, offset))
return -1;
/* Try loading from each implementation, until one succeeds. */
ret = frontswap_ops->load(type, offset, page, &exclusive);
if (ret == 0) {
inc_frontswap_loads();
if (exclusive) {
SetPageDirty(page);
__frontswap_clear(sis, offset);
}
}
return ret;
}
/*
* Invalidate any data from frontswap associated with the specified swaptype
* and offset so that a subsequent "get" will fail.
*/
void __frontswap_invalidate_page(unsigned type, pgoff_t offset)
{
struct swap_info_struct *sis = swap_info[type];
VM_BUG_ON(!frontswap_ops);
VM_BUG_ON(sis == NULL);
if (!__frontswap_test(sis, offset))
return;
frontswap_ops->invalidate_page(type, offset);
__frontswap_clear(sis, offset);
inc_frontswap_invalidates();
}
/*
* Invalidate all data from frontswap associated with all offsets for the
* specified swaptype.
*/
void __frontswap_invalidate_area(unsigned type)
{
struct swap_info_struct *sis = swap_info[type];
VM_BUG_ON(!frontswap_ops);
VM_BUG_ON(sis == NULL);
if (sis->frontswap_map == NULL)
return;
frontswap_ops->invalidate_area(type);
atomic_set(&sis->frontswap_pages, 0);
bitmap_zero(sis->frontswap_map, sis->max);
}
static int __init init_frontswap(void)
{
#ifdef CONFIG_DEBUG_FS
struct dentry *root = debugfs_create_dir("frontswap", NULL);
if (root == NULL)
return -ENXIO;
debugfs_create_u64("loads", 0444, root, &frontswap_loads);
debugfs_create_u64("succ_stores", 0444, root, &frontswap_succ_stores);
debugfs_create_u64("failed_stores", 0444, root,
&frontswap_failed_stores);
debugfs_create_u64("invalidates", 0444, root, &frontswap_invalidates);
#endif
return 0;
}
module_init(init_frontswap);
...@@ -19,12 +19,12 @@ ...@@ -19,12 +19,12 @@
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/swapops.h> #include <linux/swapops.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/frontswap.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/psi.h> #include <linux/psi.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/sched/task.h> #include <linux/sched/task.h>
#include <linux/delayacct.h> #include <linux/delayacct.h>
#include <linux/zswap.h>
#include "swap.h" #include "swap.h"
static void __end_swap_bio_write(struct bio *bio) static void __end_swap_bio_write(struct bio *bio)
...@@ -195,7 +195,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) ...@@ -195,7 +195,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
folio_unlock(folio); folio_unlock(folio);
return ret; return ret;
} }
if (frontswap_store(&folio->page) == 0) { if (zswap_store(&folio->page)) {
folio_start_writeback(folio); folio_start_writeback(folio);
folio_unlock(folio); folio_unlock(folio);
folio_end_writeback(folio); folio_end_writeback(folio);
...@@ -512,7 +512,7 @@ void swap_readpage(struct page *page, bool synchronous, struct swap_iocb **plug) ...@@ -512,7 +512,7 @@ void swap_readpage(struct page *page, bool synchronous, struct swap_iocb **plug)
} }
delayacct_swapin_start(); delayacct_swapin_start();
if (frontswap_load(page) == 0) { if (zswap_load(page)) {
SetPageUptodate(page); SetPageUptodate(page);
unlock_page(page); unlock_page(page);
} else if (data_race(sis->flags & SWP_FS_OPS)) { } else if (data_race(sis->flags & SWP_FS_OPS)) {
......
...@@ -35,13 +35,13 @@ ...@@ -35,13 +35,13 @@
#include <linux/memcontrol.h> #include <linux/memcontrol.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/oom.h> #include <linux/oom.h>
#include <linux/frontswap.h>
#include <linux/swapfile.h> #include <linux/swapfile.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/swap_slots.h> #include <linux/swap_slots.h>
#include <linux/sort.h> #include <linux/sort.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/zswap.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <linux/swapops.h> #include <linux/swapops.h>
...@@ -95,7 +95,7 @@ static PLIST_HEAD(swap_active_head); ...@@ -95,7 +95,7 @@ static PLIST_HEAD(swap_active_head);
static struct plist_head *swap_avail_heads; static struct plist_head *swap_avail_heads;
static DEFINE_SPINLOCK(swap_avail_lock); static DEFINE_SPINLOCK(swap_avail_lock);
struct swap_info_struct *swap_info[MAX_SWAPFILES]; static struct swap_info_struct *swap_info[MAX_SWAPFILES];
static DEFINE_MUTEX(swapon_mutex); static DEFINE_MUTEX(swapon_mutex);
...@@ -744,7 +744,7 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset, ...@@ -744,7 +744,7 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset,
swap_slot_free_notify = NULL; swap_slot_free_notify = NULL;
while (offset <= end) { while (offset <= end) {
arch_swap_invalidate_page(si->type, offset); arch_swap_invalidate_page(si->type, offset);
frontswap_invalidate_page(si->type, offset); zswap_invalidate(si->type, offset);
if (swap_slot_free_notify) if (swap_slot_free_notify)
swap_slot_free_notify(si->bdev, offset); swap_slot_free_notify(si->bdev, offset);
offset++; offset++;
...@@ -2343,11 +2343,10 @@ static void _enable_swap_info(struct swap_info_struct *p) ...@@ -2343,11 +2343,10 @@ static void _enable_swap_info(struct swap_info_struct *p)
static void enable_swap_info(struct swap_info_struct *p, int prio, static void enable_swap_info(struct swap_info_struct *p, int prio,
unsigned char *swap_map, unsigned char *swap_map,
struct swap_cluster_info *cluster_info, struct swap_cluster_info *cluster_info)
unsigned long *frontswap_map)
{ {
if (IS_ENABLED(CONFIG_FRONTSWAP)) zswap_swapon(p->type);
frontswap_init(p->type, frontswap_map);
spin_lock(&swap_lock); spin_lock(&swap_lock);
spin_lock(&p->lock); spin_lock(&p->lock);
setup_swap_info(p, prio, swap_map, cluster_info); setup_swap_info(p, prio, swap_map, cluster_info);
...@@ -2390,7 +2389,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) ...@@ -2390,7 +2389,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
struct swap_info_struct *p = NULL; struct swap_info_struct *p = NULL;
unsigned char *swap_map; unsigned char *swap_map;
struct swap_cluster_info *cluster_info; struct swap_cluster_info *cluster_info;
unsigned long *frontswap_map;
struct file *swap_file, *victim; struct file *swap_file, *victim;
struct address_space *mapping; struct address_space *mapping;
struct inode *inode; struct inode *inode;
...@@ -2515,12 +2513,10 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) ...@@ -2515,12 +2513,10 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
p->swap_map = NULL; p->swap_map = NULL;
cluster_info = p->cluster_info; cluster_info = p->cluster_info;
p->cluster_info = NULL; p->cluster_info = NULL;
frontswap_map = frontswap_map_get(p);
spin_unlock(&p->lock); spin_unlock(&p->lock);
spin_unlock(&swap_lock); spin_unlock(&swap_lock);
arch_swap_invalidate_area(p->type); arch_swap_invalidate_area(p->type);
frontswap_invalidate_area(p->type); zswap_swapoff(p->type);
frontswap_map_set(p, NULL);
mutex_unlock(&swapon_mutex); mutex_unlock(&swapon_mutex);
free_percpu(p->percpu_cluster); free_percpu(p->percpu_cluster);
p->percpu_cluster = NULL; p->percpu_cluster = NULL;
...@@ -2528,7 +2524,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) ...@@ -2528,7 +2524,6 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
p->cluster_next_cpu = NULL; p->cluster_next_cpu = NULL;
vfree(swap_map); vfree(swap_map);
kvfree(cluster_info); kvfree(cluster_info);
kvfree(frontswap_map);
/* Destroy swap account information */ /* Destroy swap account information */
swap_cgroup_swapoff(p->type); swap_cgroup_swapoff(p->type);
exit_swap_address_space(p->type); exit_swap_address_space(p->type);
...@@ -2995,7 +2990,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) ...@@ -2995,7 +2990,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
unsigned long maxpages; unsigned long maxpages;
unsigned char *swap_map = NULL; unsigned char *swap_map = NULL;
struct swap_cluster_info *cluster_info = NULL; struct swap_cluster_info *cluster_info = NULL;
unsigned long *frontswap_map = NULL;
struct page *page = NULL; struct page *page = NULL;
struct inode *inode = NULL; struct inode *inode = NULL;
bool inced_nr_rotate_swap = false; bool inced_nr_rotate_swap = false;
...@@ -3135,11 +3129,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) ...@@ -3135,11 +3129,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
error = nr_extents; error = nr_extents;
goto bad_swap_unlock_inode; goto bad_swap_unlock_inode;
} }
/* frontswap enabled? set up bit-per-page map for frontswap */
if (IS_ENABLED(CONFIG_FRONTSWAP))
frontswap_map = kvcalloc(BITS_TO_LONGS(maxpages),
sizeof(long),
GFP_KERNEL);
if ((swap_flags & SWAP_FLAG_DISCARD) && if ((swap_flags & SWAP_FLAG_DISCARD) &&
p->bdev && bdev_max_discard_sectors(p->bdev)) { p->bdev && bdev_max_discard_sectors(p->bdev)) {
...@@ -3192,16 +3181,15 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) ...@@ -3192,16 +3181,15 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
if (swap_flags & SWAP_FLAG_PREFER) if (swap_flags & SWAP_FLAG_PREFER)
prio = prio =
(swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT; (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT;
enable_swap_info(p, prio, swap_map, cluster_info, frontswap_map); enable_swap_info(p, prio, swap_map, cluster_info);
pr_info("Adding %uk swap on %s. Priority:%d extents:%d across:%lluk %s%s%s%s%s\n", pr_info("Adding %uk swap on %s. Priority:%d extents:%d across:%lluk %s%s%s%s\n",
p->pages<<(PAGE_SHIFT-10), name->name, p->prio, p->pages<<(PAGE_SHIFT-10), name->name, p->prio,
nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10), nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
(p->flags & SWP_SOLIDSTATE) ? "SS" : "", (p->flags & SWP_SOLIDSTATE) ? "SS" : "",
(p->flags & SWP_DISCARDABLE) ? "D" : "", (p->flags & SWP_DISCARDABLE) ? "D" : "",
(p->flags & SWP_AREA_DISCARD) ? "s" : "", (p->flags & SWP_AREA_DISCARD) ? "s" : "",
(p->flags & SWP_PAGE_DISCARD) ? "c" : "", (p->flags & SWP_PAGE_DISCARD) ? "c" : "");
(frontswap_map) ? "FS" : "");
mutex_unlock(&swapon_mutex); mutex_unlock(&swapon_mutex);
atomic_inc(&proc_poll_event); atomic_inc(&proc_poll_event);
...@@ -3231,7 +3219,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) ...@@ -3231,7 +3219,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
spin_unlock(&swap_lock); spin_unlock(&swap_lock);
vfree(swap_map); vfree(swap_map);
kvfree(cluster_info); kvfree(cluster_info);
kvfree(frontswap_map);
if (inced_nr_rotate_swap) if (inced_nr_rotate_swap)
atomic_dec(&nr_rotate_swap); atomic_dec(&nr_rotate_swap);
if (swap_file) if (swap_file)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment