From nobody Fri Apr 3 01:24:32 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3AB9937755A for ; Tue, 17 Feb 2026 20:06:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771358809; cv=none; b=gxEe4HrKJSYCdYqF91Hhpj7T4raJc7WchE6MrJ6eb+mS39J3Hf6xh5xriH7zQ0LFXG0h1xsgsRjpYBmuf03La/0yvxWUA6VR0ZMSgCdjIUZOCUriq95Z3EUqcIJw3DqGBHxp+SJWQ5Fvs0SOwZtTpsCeFzXzeOXcrIdCYJfZYxk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771358809; c=relaxed/simple; bh=RyDzMAmfxfcPT8sKIGfF1K+4m/6TkMreqQ4aKJizUJY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=O6DB3tdQTpJo97D2upAAQ3rNa+92SR6U0zT+X2MdTL/mg9T5erVDQmSDg3eEhv2FTGpwHCiIJkRSGAqdWGAFMa5FQskio24sHBsFdyzUPJoQc6tLMatbRO4ju4u3V06LvEOaoqEnKPj5PoO0lORAuWJOci1uchgdOBHKDWIYAGM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JWvha88M; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JWvha88M" Received: by smtp.kernel.org (Postfix) with ESMTPS id 141EAC19425; Tue, 17 Feb 2026 20:06:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771358809; bh=RyDzMAmfxfcPT8sKIGfF1K+4m/6TkMreqQ4aKJizUJY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=JWvha88MtRSN3jLGNG877Qt8+GHLuwstLqe2oMJrlp/3ENBnr+HOodK3xaE3rY6j4 1q+XUt9/bKP8iorcbrcuLO/GhdOj0oRazTPduR37S8qRejkL4vuoPPpmdzlg/Ds61T hP1tc0busK6vVtT32l2JWbouuKA94p6awizwvqGwcpsTLHYQUWp5rMzy4C7ooUBvW2 tAvCYLW1ch7gMOG+ED7EEFAgq0F0Reu33Ynx194KWtiI9y/MLaBk5AckZPIHgM7jWB 74mUs/yZJI8zkMA+LrN+K7l0pSuWCa2ZBB4BvQKeooWgiLZcYw5bxTlctg8iDyZfOr DpCnDw7tSCXTQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 06117E9A040; Tue, 17 Feb 2026 20:06:49 +0000 (UTC) From: Kairui Song via B4 Relay Date: Wed, 18 Feb 2026 04:06:29 +0800 Subject: [PATCH v3 04/12] mm, swap: consolidate bad slots setup and make it more robust 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: quoted-printable Message-Id: <20260218-swap-table-p3-v3-4-f4e34be021a7@tencent.com> References: <20260218-swap-table-p3-v3-0-f4e34be021a7@tencent.com> In-Reply-To: <20260218-swap-table-p3-v3-0-f4e34be021a7@tencent.com> To: linux-mm@kvack.org Cc: Andrew Morton , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Johannes Weiner , David Hildenbrand , Lorenzo Stoakes , Youngjun Park , linux-kernel@vger.kernel.org, Chris Li , Kairui Song X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1771358806; l=4411; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=dTxwU7HNi4RjZm8BIg4m/tk9gYStmKjj5MiTeMIyv7o=; b=X0FBoaZxzsjFgaOx7GXTnkZmNCoBeOVc8rrBdBmxLga4IAkX6V3jxFmOmyvmmFpMTcvJKdXBw Yoz2wOXCe4kDldrwEgD0/8IdRNTGJgxl5dcBRLKsDyf9zXElv8040Od X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= X-Endpoint-Received: by B4 Relay for kasong@tencent.com/kasong-sign-tencent with auth_id=562 X-Original-From: Kairui Song Reply-To: kasong@tencent.com From: Kairui Song In preparation for using the swap table to track bad slots directly, move the bad slot setup to one place, set up the swap_map mark, and cluster counter update together. While at it, provide more informative logs and a more robust fallback if any bad slot info looks incorrect. Fixes a potential issue that a malformed swap file may cause the cluster to be unusable upon swapon, and provides a more verbose warning on a malformed swap file Signed-off-by: Kairui Song Acked-by: Chris Li --- mm/swapfile.c | 68 +++++++++++++++++++++++++++++++++----------------------= ---- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index fb0d48681c48..91c1fa804185 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -743,13 +743,37 @@ static void relocate_cluster(struct swap_info_struct = *si, * slot. The cluster will not be added to the free cluster list, and its * usage counter will be increased by 1. Only used for initialization. */ -static int swap_cluster_setup_bad_slot(struct swap_cluster_info *cluster_i= nfo, - unsigned long offset) +static int swap_cluster_setup_bad_slot(struct swap_info_struct *si, + struct swap_cluster_info *cluster_info, + unsigned int offset, bool mask) { unsigned long idx =3D offset / SWAPFILE_CLUSTER; struct swap_table *table; struct swap_cluster_info *ci; =20 + /* si->max may got shrunk by swap swap_activate() */ + if (offset >=3D si->max && !mask) { + pr_debug("Ignoring bad slot %u (max: %u)\n", offset, si->max); + return 0; + } + /* + * Account it, skip header slot: si->pages is initiated as + * si->max - 1. Also skip the masking of last cluster, + * si->pages doesn't include that part. + */ + if (offset && !mask) + si->pages -=3D 1; + if (!si->pages) { + pr_warn("Empty swap-file\n"); + return -EINVAL; + } + /* Check for duplicated bad swap slots. */ + if (si->swap_map[offset]) { + pr_warn("Duplicated bad slot offset %d\n", offset); + return -EINVAL; + } + + si->swap_map[offset] =3D SWAP_MAP_BAD; ci =3D cluster_info + idx; if (!ci->table) { table =3D swap_table_alloc(GFP_KERNEL); @@ -3227,30 +3251,12 @@ static int setup_swap_map(struct swap_info_struct *= si, union swap_header *swap_header, unsigned long maxpages) { - unsigned long i; unsigned char *swap_map; =20 swap_map =3D vzalloc(maxpages); si->swap_map =3D swap_map; if (!swap_map) return -ENOMEM; - - swap_map[0] =3D SWAP_MAP_BAD; /* omit header page */ - for (i =3D 0; i < swap_header->info.nr_badpages; i++) { - unsigned int page_nr =3D swap_header->info.badpages[i]; - if (page_nr =3D=3D 0 || page_nr > swap_header->info.last_page) - return -EINVAL; - if (page_nr < maxpages) { - swap_map[page_nr] =3D SWAP_MAP_BAD; - si->pages--; - } - } - - if (!si->pages) { - pr_warn("Empty swap-file\n"); - return -EINVAL; - } - return 0; } =20 @@ -3281,26 +3287,28 @@ static int setup_swap_clusters_info(struct swap_inf= o_struct *si, } =20 /* - * Mark unusable pages as unavailable. The clusters aren't - * marked free yet, so no list operations are involved yet. - * - * See setup_swap_map(): header page, bad pages, - * and the EOF part of the last cluster. + * Mark unusable pages (header page, bad pages, and the EOF part of + * the last cluster) as unavailable. The clusters aren't marked free + * yet, so no list operations are involved yet. */ - err =3D swap_cluster_setup_bad_slot(cluster_info, 0); + err =3D swap_cluster_setup_bad_slot(si, cluster_info, 0, false); if (err) goto err; for (i =3D 0; i < swap_header->info.nr_badpages; i++) { unsigned int page_nr =3D swap_header->info.badpages[i]; =20 - if (page_nr >=3D maxpages) - continue; - err =3D swap_cluster_setup_bad_slot(cluster_info, page_nr); + if (!page_nr || page_nr > swap_header->info.last_page) { + pr_warn("Bad slot offset is out of border: %d (last_page: %d)\n", + page_nr, swap_header->info.last_page); + err =3D -EINVAL; + goto err; + } + err =3D swap_cluster_setup_bad_slot(si, cluster_info, page_nr, false); if (err) goto err; } for (i =3D maxpages; i < round_up(maxpages, SWAPFILE_CLUSTER); i++) { - err =3D swap_cluster_setup_bad_slot(cluster_info, i); + err =3D swap_cluster_setup_bad_slot(si, cluster_info, i, true); if (err) goto err; } --=20 2.52.0