From 31365f8d8fa5d7a30920166b8c3a60130c24412e Mon Sep 17 00:00:00 2001 From: Kairui Song Date: Thu, 1 Aug 2024 17:29:48 +0800 Subject: [PATCH] SQUASH: Fix discard of full cluster Signed-off-by: Kairui Song --- include/linux/swap.h | 1 + mm/swapfile.c | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 145e796dab84..3543ffaf982e 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -260,6 +260,7 @@ struct swap_cluster_info { #define CLUSTER_FLAG_FREE 1 /* This cluster is free */ #define CLUSTER_FLAG_NONFULL 2 /* This cluster is on nonfull list */ #define CLUSTER_FLAG_FRAG 4 /* This cluster is on nonfull list */ +#define CLUSTER_FLAG_FULL 8 /* This cluster is on full list */ /* * The first page in the swap file is the swap header, which is always marked diff --git a/mm/swapfile.c b/mm/swapfile.c index 9872e0dbfc72..5ab06a45565a 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -450,7 +450,10 @@ static void __free_cluster(struct swap_info_struct *si, struct swap_cluster_info lockdep_assert_held(&si->lock); lockdep_assert_held(&ci->lock); - list_move_tail(&ci->list, &si->free_clusters); + if (ci->flags) + list_move_tail(&ci->list, &si->free_clusters); + else + list_add_tail(&ci->list, &si->free_clusters); ci->flags = CLUSTER_FLAG_FREE; ci->order = 0; } @@ -474,7 +477,6 @@ static void swap_do_scheduled_discard(struct swap_info_struct *si) SWAPFILE_CLUSTER); spin_lock(&si->lock); - spin_lock(&ci->lock); __free_cluster(si, ci); memset(si->swap_map + idx * SWAPFILE_CLUSTER, @@ -666,7 +668,7 @@ static void cluster_alloc_range(struct swap_info_struct *si, struct swap_cluster if (ci->flags & CLUSTER_FLAG_FRAG) si->frag_cluster_nr[ci->order]--; list_move_tail(&ci->list, &si->full_clusters); - ci->flags = 0; + ci->flags = CLUSTER_FLAG_FULL; } } -- 2.45.2