From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qk1-f181.google.com (mail-qk1-f181.google.com [209.85.222.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7FB6831064E for ; Sun, 16 Nov 2025 18:13:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.181 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763316783; cv=none; b=Nuz2Ayib6owPzxDBgsZwri8R1NqifXk8Opr9qt8j6xbVkq95o7KPZWVg1ByXvdiOwRTCJBys1bGtsebetsCpUcNsu6nfdfSJOKDjykDRxKwDBr0EXRppOt3jqAnz4sLHOS4RtwR5DON2ECV16bVm015vkEgpAZBPI2V5Kf6Qj7c= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763316783; c=relaxed/simple; bh=6OsRHbmgOTwVsFcR3lVMx1dRJKVkODUkJD3wllbx8Qw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=U19i5EV6g+J/JRzGNuZ1c69OLh3RsKA/x0vFbWr+Ddm+2caTaN4FTqo6NuDprtDmm9PM+uuoEX4upNIphDlxXFOLpaSf2EI67Li2hM5Q4mydRbBqwEspiCaAmvW8J+cMAvNYTAzTmoIv94MnHzBuqTJlnhJu9JuJOOYup4WO7aE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=BAgUl3LY; arc=none smtp.client-ip=209.85.222.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BAgUl3LY" Received: by mail-qk1-f181.google.com with SMTP id af79cd13be357-8b2ec756de0so27842385a.3 for ; Sun, 16 Nov 2025 10:13:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1763316780; x=1763921580; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=N5dyJSqyOf74su3zx4aCp7vUNrol9ZYcdrrVb5NykSY=; b=BAgUl3LYhkh1UoM3MNNRfdePJgaLgy7jkIkGPLRp8ZBAqFaz4D2oWBqI718mY9ihtE M2mLOgb3PfEr0c6lGdVjfNdJ8pnxwFLd0jdhu/yBJbxxifKc0DxY85y1FttVim5tLB2R 6pq7k/rYQ1Y6LoJId+IhlYm2W/yOAUhrBT1DePTJlKqrk+esydfRrvN8+TKQesUspIdT xqSKEdPGEKYOzjEtVOEDRylE+74GuMRGcZpuNz0az9f4ZMj4M7YoXRUKvYo0wyAK5hFu v5982CV1HDUo/PW6d3aOjqNuJQshGvwhx1YwbeZBo6AB9ecaaAIxWLyqSP54Fc+9uMvx c+ng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763316780; x=1763921580; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=N5dyJSqyOf74su3zx4aCp7vUNrol9ZYcdrrVb5NykSY=; b=BsqfHyzpJMbxyzqEIQ8sRzZUs0mYVYaUJ1EFqicl3viaUg/fXgM0AgRg62MXtWfSFw X9Lyw015vYn710GhMHhvGsVJaT2I32IbKcjbPXsLhaLa9MI2ciIY64kg1aE/tG+L2Frf pFLc4xBLy0FQPZpQPh8Pv/EaVlm3W+DQA/sbL15+uBnw5kquDqD2ptOUUL2wxi4kdLc3 1RVEk0WzySfvuv5RFU71RfpGZw6KT2/iceLrUliazYIMAq6tk1O9Kd2tSAuwd0/kTh4N 8sWbDaEmAwmz9YPvPIxh2zPoaozGv+gtJt6ss7hvsVhkz7m+aL0FhInrqlNFiMp++RBJ E5nA== X-Forwarded-Encrypted: i=1; AJvYcCWaOvazXCBgeyW4KbCNGvSbEhutPVL2g1gG4SgureiNcA4BvrUAfAoE7Ns7KTWumv1KtSthKcTI2FCxrPQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yzz3wvtRWDbvW4LQgoQE3F/QxpsT61z9Jap07jQMiAl5ZAMsujR OMpsExtS1LOebVfTx6kv6BUIPXVHcSpBeXbnbtGRs0lb1mUWI1h7r9ur X-Gm-Gg: ASbGnctzXl5v2mqdmLIgGHIXZOF27z/b+X1L4ij7yjPhQORiYf2oHurwOgdLjaRl8tf AVQqAbiRWZhf/rh0pP2qFR/BQYn/Pz1dfNmYmMqYVSdcelC4Ie8mara4yabvhETxVLH9bxGqYjd SWzo5oVb6sdHYfD76sQQfMEki9F4neMuzHsWWpFOi6700VDIwdieQhZvkjRWpwNAtsgZoOpbdfy YG7J7iO0g/5HKSE87jyQxs6Sw86gTVocWkjxhE4YF1ipkvkOooMl6Fx6BMPlbhSLuunYemfCfvn XWfdsZik8loRwycKt12HiOviReeC9ieX9SBfMHs4tFPh24sG5Ou8C0U03Zyz2qoDByVWyjm2TJs tsmS/xXi7Y626PQVHEJKZQoWZdjE2hdhwyvqcVFLx+BjFm+B7hCGGQ3NQ3MaKLgENnq8dcQot4T /2EcpRwcaw0Awc4HOGZSFYhpeqInNWdG/xl9e84dYkTA== X-Google-Smtp-Source: AGHT+IF6z6G+a6/yk1iW5mtw+5/zL+FuJ/bF3edg1gcNLVbNQRnP7GcktPIDkmFrBLAYTvqyfjba7Q== X-Received: by 2002:a05:620a:c41:b0:8b2:7558:409c with SMTP id af79cd13be357-8b2c3162bb8mr1383729985a.36.1763316780354; Sun, 16 Nov 2025 10:13:00 -0800 (PST) Received: from [127.0.0.1] ([101.32.222.185]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8b2e089b436sm305447785a.45.2025.11.16.10.12.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 16 Nov 2025 10:12:59 -0800 (PST) From: Kairui Song Date: Mon, 17 Nov 2025 02:11:51 +0800 Subject: [PATCH v2 10/19] mm, swap: consolidate cluster reclaim and check logic Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20251117-swap-table-p2-v2-10-37730e6ea6d5@tencent.com> References: <20251117-swap-table-p2-v2-0-37730e6ea6d5@tencent.com> In-Reply-To: <20251117-swap-table-p2-v2-0-37730e6ea6d5@tencent.com> To: linux-mm@kvack.org Cc: Andrew Morton , Baoquan He , Barry Song , Chris Li , Nhat Pham , Yosry Ahmed , David Hildenbrand , Johannes Weiner , Youngjun Park , Hugh Dickins , Baolin Wang , Ying Huang , Kemeng Shi , Lorenzo Stoakes , "Matthew Wilcox (Oracle)" , linux-kernel@vger.kernel.org, Kairui Song X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1763316712; l=4184; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=XNFtoENDe576WtAy1cTHm6/Bj/RVg2NJetPJJZ7TblY=; b=5N1PHKvjcqHSh3B3QLL//ogepK7lUfOgllKkEU/qtEVGKobcGxAU2lHWLbmdB2VYPYdqPhLBI RQpjpzumpyFCp0HIqbrDd99K3StPeVO3epQvKQeBZ5vOlCM6O4FvHA4 X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= From: Kairui Song Swap cluster cache reclaim requires releasing the lock, so some extra checks are needed after the reclaim. To prepare for checking swap cache using the swap table directly, consolidate the swap cluster reclaim and check the logic. Also, adjust it very slightly. By moving the cluster empty and usable check into the reclaim helper, it will avoid a redundant scan of the slots if the cluster is empty. And always scan the whole region during reclaim, don't skip slots covered by a reclaimed folio. Because the reclaim is lockless, it's possible that new cache lands at any time. And for allocation, we want all caches to be reclaimed to avoid fragmentation. And besides, if the scan offset is not aligned with the size of the reclaimed folio, we are skipping some existing caches. There should be no observable behavior change, which might slightly improve the fragmentation issue or performance. Signed-off-by: Kairui Song --- mm/swapfile.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index d2e60734ce8f..d57e83a4d0a7 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -778,42 +778,50 @@ static int swap_cluster_setup_bad_slot(struct swap_cluster_info *cluster_info, return 0; } -static bool cluster_reclaim_range(struct swap_info_struct *si, - struct swap_cluster_info *ci, - unsigned long start, unsigned long end) +static unsigned int cluster_reclaim_range(struct swap_info_struct *si, + struct swap_cluster_info *ci, + unsigned long start, unsigned int order) { + unsigned int nr_pages = 1 << order; + unsigned long offset = start, end = start + nr_pages; unsigned char *map = si->swap_map; - unsigned long offset = start; int nr_reclaim; spin_unlock(&ci->lock); do { switch (READ_ONCE(map[offset])) { case 0: - offset++; break; case SWAP_HAS_CACHE: nr_reclaim = __try_to_reclaim_swap(si, offset, TTRS_ANYWAY); - if (nr_reclaim > 0) - offset += nr_reclaim; - else + if (nr_reclaim < 0) goto out; break; default: goto out; } - } while (offset < end); + } while (++offset < end); out: spin_lock(&ci->lock); + + /* + * We just dropped ci->lock so cluster could be used by another + * order or got freed, check if it's still usable or empty. + */ + if (!cluster_is_usable(ci, order)) + return SWAP_ENTRY_INVALID; + if (cluster_is_empty(ci)) + return cluster_offset(si, ci); + /* * Recheck the range no matter reclaim succeeded or not, the slot * could have been be freed while we are not holding the lock. */ for (offset = start; offset < end; offset++) if (READ_ONCE(map[offset])) - return false; + return SWAP_ENTRY_INVALID; - return true; + return start; } static bool cluster_scan_range(struct swap_info_struct *si, @@ -901,7 +909,7 @@ static unsigned int alloc_swap_scan_cluster(struct swap_info_struct *si, unsigned long start = ALIGN_DOWN(offset, SWAPFILE_CLUSTER); unsigned long end = min(start + SWAPFILE_CLUSTER, si->max); unsigned int nr_pages = 1 << order; - bool need_reclaim, ret; + bool need_reclaim; lockdep_assert_held(&ci->lock); @@ -913,20 +921,13 @@ static unsigned int alloc_swap_scan_cluster(struct swap_info_struct *si, if (!cluster_scan_range(si, ci, offset, nr_pages, &need_reclaim)) continue; if (need_reclaim) { - ret = cluster_reclaim_range(si, ci, offset, offset + nr_pages); - /* - * Reclaim drops ci->lock and cluster could be used - * by another order. Not checking flag as off-list - * cluster has no flag set, and change of list - * won't cause fragmentation. - */ + found = cluster_reclaim_range(si, ci, offset, order); if (!cluster_is_usable(ci, order)) goto out; - if (cluster_is_empty(ci)) - offset = start; /* Reclaim failed but cluster is usable, try next */ - if (!ret) + if (!found) continue; + offset = found; } if (!cluster_alloc_range(si, ci, offset, usage, order)) break; -- 2.51.2