From nobody Mon Feb 9 17:34:55 2026 Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) (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 30DCC34A3D0 for ; Wed, 28 Jan 2026 09:30:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769592648; cv=none; b=rHezWVhSRU9VhTXDqRT7XGoS55G3wB2l2KzQoHdSmrAM4qKSxiLamnm5TQ/cZ34NDNli2BLtX5lz6YlfOkcSSUSqC/6iAcSfzeZI/dRcCgpgsVSTymFKOnKjeAmqMkeCtt5605N82mJJ1p8snoBhF983nbTxgJWazXONzHAmA/4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769592648; c=relaxed/simple; bh=OWJY00Wf2dIBc05Nz8hzedH27aMPMMOuwTeZeud6eu0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FwPM+Fiq7MpZ0O1PL7AuEq3U+T0d3Vaz80wDMLDVerQgRb/K9QUXIXXQWWpF+ScTvTP3EAayPCkC8s5+vhglC4TtSWcyqQSoyQcfMtnmEOtpgzgbbYFeVKr+joMajWlztfZnkXU6pgBDYbX5qrOTjQeC1US1qcRT+vjshuObBkk= 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=A3OkND/R; arc=none smtp.client-ip=209.85.216.44 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="A3OkND/R" Received: by mail-pj1-f44.google.com with SMTP id 98e67ed59e1d1-34c868b197eso5565843a91.2 for ; Wed, 28 Jan 2026 01:30:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769592646; x=1770197446; 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=aAw5ZLwfH3aOqNw+8qnqKgdPaynl21dDWoO/xPxb8Vc=; b=A3OkND/R6YUbX9rP3ehMt56b6CDeZ2MIFOvfiO3DDbadpYkXpHUk5ISyfrU8NqEIUE SPiJGL5ahwONH1PQVth2xGIo3914/cG5f+Fu/aBenT56BWjQB6rgz2XQgtZVyFVGSUWu 5iOvGpRYtJixMXvylt376CL7RAxx21R4uMfdC+FoNFcvAVa3OAfIR0JSmc8U/PLjvuoV jEhFKA33yK5+BZlR+du3pZalCK4GX59sJv59dtJWKqqPhKqHB1yQTLPICiP00pnIFEW3 Nofzsqk4nndvq0cx/SfCuaJaXC7nkkxtpumZFGiTBD8JTM3oZWw6LL9tNncwAd+SFGxk dHbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769592646; x=1770197446; 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=aAw5ZLwfH3aOqNw+8qnqKgdPaynl21dDWoO/xPxb8Vc=; b=t4YiaS2vFHxMqxlG07clFzS6l8S6wlbNwR+dPk3Vn9bErphXkuwrNZfTdmKUcCWX5w Qrsqx8IXvgYKaMdmDejbrQdrstNDv58LCUj48daIIza9JE4hbhWhcxAaeUvZWQUjISvC 9h0g2pFnTQzrERshZfww/18SN6UEJ3aSgsKYtJUUBXSsUOaHbKCI2zH/3Us/m/Xu/Mbq 5/FLHbLqY7eyQx/PamartzvKxyS9LXHM2nC7KcIaMavqAwA1INFKbWFfL8g9q4ny7JqN g34fX9R//67ZiA72ZQn7A1ZNAsAWa4NlBiot8rbiHIKiwTTk0sHg7k4S2xs88sCeg2Sz ++sg== X-Forwarded-Encrypted: i=1; AJvYcCVnvd/PUkov+ZCkmbP0fzRGXFcf8vjkQmRVsuY2RpvcH6oc50WWjMPU6MyQLiCvdpTnTwxsHL6xxnlkdKo=@vger.kernel.org X-Gm-Message-State: AOJu0YznOrOkybLWdFW99Ezgqdp/gsaxamyyHDJgLcb1Jr8lEmx0rGD6 4bioKz5+EHRfdv5Lq5luJp0LjDziVOy9f0z8pB9TiLFugeJaI0Ar3pF2 X-Gm-Gg: AZuq6aKjqK3t8cWBjgt31iFUPnFMJf6lty0fkSEIqIcbzcHBA8a39LMKv/TWAiqQIyT Z7FJw0+8ua+Qs+2bJTMxYuK0nU8fMwGs3Z0X3CCJ+J6VTranJCoRygeAeS8pmDwpeRwT+BCzeOM lu14i3Bt0OQKUAZqPsFcf6r8hLGlQUL8BExV8gE7ScDi9I1+0cSUSUZ3sFBZh/rmNRW3yY0QXS8 Phz4Qr354V0KKm7n86O+0wCihyR9aUjFyK2kl48r6ncEyhte9p485a60hi7er5eauLnfwQW50y8 I3eYoR6ysmWtHvXqQG4jYVrA7pemzIcdf5/YCoCZPjnF1TVQ6osHabhNoLL8rKrpTEq0bZjvGai li1fH30doS8zGh6idKwF88w6ezP5HlQeXIZpWDHwy9HmlGaI2/eRHCiZHhHbfMwNPtq3KpupCJo 4rXkurENryaOghGcpgMBoOF2XvxZJIJGIfChoFwN5X6w6wxmJiITJdYq9Emg== X-Received: by 2002:a17:90b:2f04:b0:340:ad5e:cb with SMTP id 98e67ed59e1d1-353fecdcfabmr4259352a91.8.1769592646111; Wed, 28 Jan 2026 01:30:46 -0800 (PST) Received: from [127.0.0.1] ([43.132.141.21]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3540f3eca6dsm1872235a91.15.2026.01.28.01.30.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 28 Jan 2026 01:30:45 -0800 (PST) From: Kairui Song Date: Wed, 28 Jan 2026 17:28:28 +0800 Subject: [PATCH v2 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: <20260128-swap-table-p3-v2-4-fe0b67ef0215@tencent.com> References: <20260128-swap-table-p3-v2-0-fe0b67ef0215@tencent.com> In-Reply-To: <20260128-swap-table-p3-v2-0-fe0b67ef0215@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=1769592628; l=4411; i=kasong@tencent.com; s=kasong-sign-tencent; h=from:subject:message-id; bh=OidTajkMc0iGAT4CQSZ4FaMMIJHOoz6IAuhiV5n7RgI=; b=cmDmAT8wUMiXX1gPvgA7bHsM5uiECNHeKtIvXly1+RBv9uooWAdTksHnja5oCbt81l6FmPKio PhDaU+N3Zy1AhsScxqi1FhSMKzBvxMFEkNRKnMayV5T5SAlUDMCxC8G X-Developer-Key: i=kasong@tencent.com; a=ed25519; pk=kCdoBuwrYph+KrkJnrr7Sm1pwwhGDdZKcKrqiK8Y1mI= 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 --- mm/swapfile.c | 68 +++++++++++++++++++++++++++++++++----------------------= ---- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/mm/swapfile.c b/mm/swapfile.c index 80bf0ea098f6..df8b13eecab1 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); @@ -3216,30 +3240,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 @@ -3270,26 +3276,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