1

mm: remove code to handle same filled pages

With an earlier commit to handle zero-filled pages in swap directly, and
with only 1% of the same-filled pages being non-zero, zswap no longer
needs to handle same-filled pages and can just work on compressed pages.

Link: https://lkml.kernel.org/r/20240823190545.979059-3-usamaarif642@gmail.com
Signed-off-by: Usama Arif <usamaarif642@gmail.com>
Reviewed-by: Chengming Zhou <chengming.zhou@linux.dev>
Acked-by: Yosry Ahmed <yosryahmed@google.com>
Reviewed-by: Nhat Pham <nphamcs@gmail.com>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Usama Arif 2024-08-23 20:04:40 +01:00 committed by Andrew Morton
parent 0ca0c24e32
commit 20a5532ffa

View File

@ -44,8 +44,6 @@
**********************************/
/* The number of compressed pages currently stored in zswap */
atomic_t zswap_stored_pages = ATOMIC_INIT(0);
/* The number of same-value filled pages currently stored in zswap */
static atomic_t zswap_same_filled_pages = ATOMIC_INIT(0);
/*
* The statistics below are not protected from concurrent access for
@ -185,8 +183,7 @@ static struct shrinker *zswap_shrinker;
*
* swpentry - associated swap entry, the offset indexes into the red-black tree
* length - the length in bytes of the compressed page data. Needed during
* decompression. For a same value filled page length is 0, and both
* pool and lru are invalid and must be ignored.
* decompression.
* referenced - true if the entry recently entered the zswap pool. Unset by the
* writeback logic. The entry is only reclaimed by the writeback
* logic if referenced is unset. See comments in the shrinker
@ -202,10 +199,7 @@ struct zswap_entry {
unsigned int length;
bool referenced;
struct zswap_pool *pool;
union {
unsigned long handle;
unsigned long value;
};
unsigned long handle;
struct obj_cgroup *objcg;
struct list_head lru;
};
@ -801,13 +795,9 @@ static void zswap_entry_cache_free(struct zswap_entry *entry)
*/
static void zswap_entry_free(struct zswap_entry *entry)
{
if (!entry->length)
atomic_dec(&zswap_same_filled_pages);
else {
zswap_lru_del(&zswap_list_lru, entry);
zpool_free(entry->pool->zpool, entry->handle);
zswap_pool_put(entry->pool);
}
zswap_lru_del(&zswap_list_lru, entry);
zpool_free(entry->pool->zpool, entry->handle);
zswap_pool_put(entry->pool);
if (entry->objcg) {
obj_cgroup_uncharge_zswap(entry->objcg, entry->length);
obj_cgroup_put(entry->objcg);
@ -1277,11 +1267,6 @@ static unsigned long zswap_shrinker_count(struct shrinker *shrinker,
* This ensures that the better zswap compresses memory, the fewer
* pages we will evict to swap (as it will otherwise incur IO for
* relatively small memory saving).
*
* The memory saving factor calculated here takes same-filled pages into
* account, but those are not freeable since they almost occupy no
* space. Hence, we may scale nr_freeable down a little bit more than we
* should if we have a lot of same-filled pages.
*/
return mult_frac(nr_freeable, nr_backing, nr_stored);
}
@ -1416,42 +1401,6 @@ resched:
} while (zswap_total_pages() > thr);
}
/*********************************
* same-filled functions
**********************************/
static bool zswap_is_folio_same_filled(struct folio *folio, unsigned long *value)
{
unsigned long *data;
unsigned long val;
unsigned int pos, last_pos = PAGE_SIZE / sizeof(*data) - 1;
bool ret = false;
data = kmap_local_folio(folio, 0);
val = data[0];
if (val != data[last_pos])
goto out;
for (pos = 1; pos < last_pos; pos++) {
if (val != data[pos])
goto out;
}
*value = val;
ret = true;
out:
kunmap_local(data);
return ret;
}
static void zswap_fill_folio(struct folio *folio, unsigned long value)
{
unsigned long *data = kmap_local_folio(folio, 0);
memset_l(data, value, PAGE_SIZE / sizeof(unsigned long));
kunmap_local(data);
}
/*********************************
* main API
**********************************/
@ -1463,7 +1412,6 @@ bool zswap_store(struct folio *folio)
struct zswap_entry *entry, *old;
struct obj_cgroup *objcg = NULL;
struct mem_cgroup *memcg = NULL;
unsigned long value;
VM_WARN_ON_ONCE(!folio_test_locked(folio));
VM_WARN_ON_ONCE(!folio_test_swapcache(folio));
@ -1496,13 +1444,6 @@ bool zswap_store(struct folio *folio)
goto reject;
}
if (zswap_is_folio_same_filled(folio, &value)) {
entry->length = 0;
entry->value = value;
atomic_inc(&zswap_same_filled_pages);
goto store_entry;
}
/* if entry is successfully added, it keeps the reference */
entry->pool = zswap_pool_current_get();
if (!entry->pool)
@ -1520,7 +1461,6 @@ bool zswap_store(struct folio *folio)
if (!zswap_compress(folio, entry))
goto put_pool;
store_entry:
entry->swpentry = swp;
entry->objcg = objcg;
entry->referenced = true;
@ -1569,13 +1509,9 @@ store_entry:
return true;
store_failed:
if (!entry->length)
atomic_dec(&zswap_same_filled_pages);
else {
zpool_free(entry->pool->zpool, entry->handle);
zpool_free(entry->pool->zpool, entry->handle);
put_pool:
zswap_pool_put(entry->pool);
}
zswap_pool_put(entry->pool);
freepage:
zswap_entry_cache_free(entry);
reject:
@ -1638,10 +1574,7 @@ bool zswap_load(struct folio *folio)
if (!entry)
return false;
if (entry->length)
zswap_decompress(entry, folio);
else
zswap_fill_folio(folio, entry->value);
zswap_decompress(entry, folio);
count_vm_event(ZSWPIN);
if (entry->objcg)
@ -1744,8 +1677,6 @@ static int zswap_debugfs_init(void)
zswap_debugfs_root, NULL, &total_size_fops);
debugfs_create_atomic_t("stored_pages", 0444,
zswap_debugfs_root, &zswap_stored_pages);
debugfs_create_atomic_t("same_filled_pages", 0444,
zswap_debugfs_root, &zswap_same_filled_pages);
return 0;
}