]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mm, swap: remove contention workaround for swap cache
authorKairui Song <kasong@tencent.com>
Tue, 16 Sep 2025 16:00:58 +0000 (00:00 +0800)
committerAndrew Morton <akpm@linux-foundation.org>
Sun, 21 Sep 2025 21:22:25 +0000 (14:22 -0700)
Swap cluster setup will try to shuffle the clusters on initialization.  It
was helpful to avoid contention for the swap cache space.  The cluster
size (2M) was much smaller than each swap cache space (64M), so shuffling
the cluster means the allocator will try to allocate swap slots that are
in different swap cache spaces for each CPU, reducing the chance of two
CPUs using the same swap cache space, and hence reducing the contention.

Now, swap cache is managed by swap clusters, this shuffle is pointless.
Just remove it, and clean up related macros.

This also improves the HDD swap performance as shuffling IO is a bad idea
for HDD, and now the shuffling is gone.  Test have shown a ~40%
performance gain for HDD [1]:

Doing sequential swap in of 8G data using 8 processes with usemem, average
of 3 test runs:

Before: 1270.91 KB/s per process
After:  1849.54 KB/s per process

Link: https://lore.kernel.org/linux-mm/CAMgjq7AdauQ8=X0zeih2r21QoV=-WWj1hyBxLWRzq74n-C=-Ng@mail.gmail.com/
Link: https://lkml.kernel.org/r/20250916160100.31545-14-ryncsn@gmail.com
Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202504241621.f27743ec-lkp@intel.com
Signed-off-by: Kairui Song <kasong@tencent.com>
Acked-by: Chris Li <chrisl@kernel.org>
Reviewed-by: Barry Song <baohua@kernel.org>
Acked-by: David Hildenbrand <david@redhat.com>
Suggested-by: Chris Li <chrisl@kernel.org>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: "Huang, Ying" <ying.huang@linux.alibaba.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Kemeng Shi <shikemeng@huaweicloud.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Yosry Ahmed <yosryahmed@google.com>
Cc: Zi Yan <ziy@nvidia.com>
Cc: SeongJae Park <sj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/swap.h
mm/swapfile.c
mm/zswap.c

index adcd85fa85381fb41a284cb77b6581400bdca40e..fe5c209220828059d91fbf6a337092459550d14e 100644 (file)
--- a/mm/swap.h
+++ b/mm/swap.h
@@ -198,10 +198,6 @@ int swap_writeout(struct folio *folio, struct swap_iocb **swap_plug);
 void __swap_writepage(struct folio *folio, struct swap_iocb **swap_plug);
 
 /* linux/mm/swap_state.c */
-/* One swap address space for each 64M swap space */
-#define SWAP_ADDRESS_SPACE_SHIFT       14
-#define SWAP_ADDRESS_SPACE_PAGES       (1 << SWAP_ADDRESS_SPACE_SHIFT)
-#define SWAP_ADDRESS_SPACE_MASK                (SWAP_ADDRESS_SPACE_PAGES - 1)
 extern struct address_space swap_space __ro_after_init;
 static inline struct address_space *swap_address_space(swp_entry_t entry)
 {
index b183e96be2892f5afde19f679a23ed9d8a2fb9f0..314c5c10d3bd9513ace720f44626519b5e5f29cc 100644 (file)
@@ -3204,21 +3204,14 @@ static int setup_swap_map(struct swap_info_struct *si,
        return 0;
 }
 
-#define SWAP_CLUSTER_INFO_COLS                                         \
-       DIV_ROUND_UP(L1_CACHE_BYTES, sizeof(struct swap_cluster_info))
-#define SWAP_CLUSTER_SPACE_COLS                                                \
-       DIV_ROUND_UP(SWAP_ADDRESS_SPACE_PAGES, SWAPFILE_CLUSTER)
-#define SWAP_CLUSTER_COLS                                              \
-       max_t(unsigned int, SWAP_CLUSTER_INFO_COLS, SWAP_CLUSTER_SPACE_COLS)
-
 static struct swap_cluster_info *setup_clusters(struct swap_info_struct *si,
                                                union swap_header *swap_header,
                                                unsigned long maxpages)
 {
        unsigned long nr_clusters = DIV_ROUND_UP(maxpages, SWAPFILE_CLUSTER);
        struct swap_cluster_info *cluster_info;
-       unsigned long i, j, idx;
        int err = -ENOMEM;
+       unsigned long i;
 
        cluster_info = kvcalloc(nr_clusters, sizeof(*cluster_info), GFP_KERNEL);
        if (!cluster_info)
@@ -3267,22 +3260,13 @@ static struct swap_cluster_info *setup_clusters(struct swap_info_struct *si,
                INIT_LIST_HEAD(&si->frag_clusters[i]);
        }
 
-       /*
-        * Reduce false cache line sharing between cluster_info and
-        * sharing same address space.
-        */
-       for (j = 0; j < SWAP_CLUSTER_COLS; j++) {
-               for (i = 0; i < DIV_ROUND_UP(nr_clusters, SWAP_CLUSTER_COLS); i++) {
-                       struct swap_cluster_info *ci;
-                       idx = i * SWAP_CLUSTER_COLS + j;
-                       ci = cluster_info + idx;
-                       if (idx >= nr_clusters)
-                               continue;
-                       if (ci->count) {
-                               ci->flags = CLUSTER_FLAG_NONFULL;
-                               list_add_tail(&ci->list, &si->nonfull_clusters[0]);
-                               continue;
-                       }
+       for (i = 0; i < nr_clusters; i++) {
+               struct swap_cluster_info *ci = &cluster_info[i];
+
+               if (ci->count) {
+                       ci->flags = CLUSTER_FLAG_NONFULL;
+                       list_add_tail(&ci->list, &si->nonfull_clusters[0]);
+               } else {
                        ci->flags = CLUSTER_FLAG_FREE;
                        list_add_tail(&ci->list, &si->free_clusters);
                }
index 1b1edecde6a79ae42ecb2cd947ee63820aa256cc..c1af782e54ec60a2296e2f3dccd19fdca8a21cda 100644 (file)
@@ -225,10 +225,13 @@ static bool zswap_has_pool;
 * helpers and fwd declarations
 **********************************/
 
+/* One swap address space for each 64M swap space */
+#define ZSWAP_ADDRESS_SPACE_SHIFT 14
+#define ZSWAP_ADDRESS_SPACE_PAGES (1 << ZSWAP_ADDRESS_SPACE_SHIFT)
 static inline struct xarray *swap_zswap_tree(swp_entry_t swp)
 {
        return &zswap_trees[swp_type(swp)][swp_offset(swp)
-               >> SWAP_ADDRESS_SPACE_SHIFT];
+               >> ZSWAP_ADDRESS_SPACE_SHIFT];
 }
 
 #define zswap_pool_debug(msg, p)                       \
@@ -1674,7 +1677,7 @@ int zswap_swapon(int type, unsigned long nr_pages)
        struct xarray *trees, *tree;
        unsigned int nr, i;
 
-       nr = DIV_ROUND_UP(nr_pages, SWAP_ADDRESS_SPACE_PAGES);
+       nr = DIV_ROUND_UP(nr_pages, ZSWAP_ADDRESS_SPACE_PAGES);
        trees = kvcalloc(nr, sizeof(*tree), GFP_KERNEL);
        if (!trees) {
                pr_err("alloc failed, zswap disabled for swap type %d\n", type);