From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from stravinsky.debian.org (stravinsky.debian.org [82.195.75.108]) (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 BBAC441D12D for ; Mon, 10 Aug 2026 16:28:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=82.195.75.108 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786379296; cv=none; b=fgab+1RhfzgqDmsV0m5ym+WbpvzIRddkcGkC/PuwU2sIAqsD0CcdiJ6ak43zdvBGev4JnqaXC1lzaTlqycluVmOUj4MTCaRE4eAFg1IboG3OyH0PlPlXmR3i+cdJUZmJzOdv0QijcZIq7CzUjZeegjP3GcxHrcj0+NSD5lnuqAQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786379296; c=relaxed/simple; bh=MqqCc24oSI55SE/DlZ1XKDzsXt4cdmCRfefdgxzpBK0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sf8NB1PzxsD1AVOxuBwMc+GK3Lu9MU8MZ9qO/Z6wOdUnrNAZoVH66w6y+2ZcGS5MZE9f2nGAr+o88iphpDW2XcbJgLrt89KyZXpleIkQtsTT3gv3qwxUgmtWKTu3I7p/yaf1y0n8oHb6PsCNZVUaHQ/YlBV07xgL0hWoSOqTXp0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=debian.org; spf=pass smtp.mailfrom=debian.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b=AB6MGyo3; arc=none smtp.client-ip=82.195.75.108 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=debian.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b="AB6MGyo3" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debian.org; s=smtpauto.stravinsky; h=X-Debian-User:Cc:To:In-Reply-To:References: Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date: From:Reply-To:Content-ID:Content-Description; bh=OSmw4/JATZovKQ82nG8xj7k3y5w0Jj+3EtzqrkfFalA=; b=AB6MGyo3gw+2RDp5miWNY20TK6 pJAKLOjit0gHXPP9YB2LYkP4Yyd1Fd+gDj4OdnSs7dwu8joPMpKM2R7cecwRtp/ROdOyx3J1qzUle z0VFdpXoZ8aY3adq30wDtDWDPdwcLGnOYG7CJIHp1eLrmmnNF/E7oexhzC2fRBFsN+eyfeYfFD2TA JmHdNnTvAPa5QuUvXzgNqs4E71UF4Jey+NvsfxOKmMAgR0/b5aHSW3K/E9iODpOPhFkiy6k8XbJo/ WgXd+DhbNFcgp0oZwQlaf2oIXJo0d48RyYL9ECLUw8KRbEEe/uORMAqSmFjF+zqwjxFOxiJG2UdmG NYStYK1A==; Received: from authenticated-user by stravinsky.debian.org with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.96) (envelope-from ) id 1wtSqv-002ufJ-0j; Mon, 10 Aug 2026 16:27:54 +0000 From: Breno Leitao Date: Mon, 10 Aug 2026 09:26:50 -0700 Subject: [PATCH 2/3] mm, swap: distinguish a malformed swap entry from a dying device 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: <20260810-swap-v1-2-375ef0767206@debian.org> References: <20260810-swap-v1-0-375ef0767206@debian.org> In-Reply-To: <20260810-swap-v1-0-375ef0767206@debian.org> To: Andrew Morton , Chris Li , Kairui Song , Kemeng Shi , Nhat Pham , Baoquan He , Barry Song , Youngjun Park , David Hildenbrand , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jann Horn , Pedro Falcato , Hugh Dickins , Baolin Wang , Peter Xu , Johannes Weiner , Yosry Ahmed , Chengming Zhou Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, kernel-team@meta.com, Breno Leitao X-Mailer: b4 0.16-dev-f8e9d X-Developer-Signature: v=1; a=openpgp-sha256; l=5482; i=leitao@debian.org; h=from:subject:message-id; bh=MqqCc24oSI55SE/DlZ1XKDzsXt4cdmCRfefdgxzpBK0=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBqefvp5TjJccBIh+J0r6eZ4piAUO/GtD+HNrZmI 4QZrutDYe+JAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCann76QAKCRA1o5Of/Hh3 bb2VD/9Vxf3WlBBc2dcGI4uVUmsmR7oy86IfaeOP4RDEzioh21udsESJl837Ovv5AO0oPcp7xF4 AAW6ZgWuN+avbIsYeuFdvqsRnTusqWbNVqKb44YKTv8VWAxbL6Qfu0DRKUB4HHGvm6y/qYlVKAQ xirzjsPSgLnbgz59SVclw+kDPssDXX+ut5/S8VQWgNb5Jvvc6V4jepCcRBq4dPrkP23Lbf9WOI/ RbXTt0VtoYM0MmprrESBwNXumNFBvcQj+YmvdEG55hZWwwjv63qV+q5RkWK0PlD5sB3hcQH4shS /9SoPlqn7Q5boo0JBOtdPkahbJdeKrP+mkwwGFdViT7Gb+F4pez1wv/52qoGrE0wxxlgfYV2NaS +3NES/FWfzgE0KT+M8G8FRBloANBMM8/hSAXWq7i4n5pD3R5QrxasSUvzh7ymSJ9GyxN0Wf4Fr7 PdR/u3eMWkB9q3XO0Caq/S2mv96+fgZF5rVM7h/A36QlYZW8PnR71n5nDYiOuEFQjsXglJmSke5 neqf3Atzo+YwAIn32kd3d1ZNhxTuWfvOWPAk/qoInl24R/Vt6vtyQfj0oBP7oDf5WSXOMBKRGMq OilHxNFDDESrauSetRj+/t+iJB99ZOqZ9tG5KbvGvV6I4rQYzbJ7huLa8xjUiVHQCgL2ASvxDOa uaQhHQYgEW4cYYw== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D X-Debian-User: leitao get_swap_device() returns NULL both for an entry that can never name a slot on any device and for a device that swapoff is taking away. The first never becomes valid, the second does, and callers cannot tell them apart. Return ERR_PTR(-EINVAL) for the two malformed cases and keep NULL for swapoff. Callers bail out on failure either way, so switch them to IS_ERR_OR_NULL() and clear si where the cleanup path would otherwise put an ERR_PTR. No functional change. Signed-off-by: Breno Leitao --- mm/memory.c | 4 +++- mm/mincore.c | 2 +- mm/shmem.c | 2 +- mm/swap_state.c | 4 ++-- mm/swapfile.c | 13 ++++++++----- mm/userfaultfd.c | 3 ++- mm/zswap.c | 2 +- 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index d9cf941967cf0..4238778b66c42 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -4956,8 +4956,10 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) /* Prevent swapoff from happening to us. */ si = get_swap_device(entry); - if (unlikely(!si)) + if (IS_ERR_OR_NULL(si)) { + si = NULL; goto out; + } folio = swap_cache_get_folio(entry); if (folio) diff --git a/mm/mincore.c b/mm/mincore.c index ff4ac82817683..c086836bc4bcc 100644 --- a/mm/mincore.c +++ b/mm/mincore.c @@ -71,7 +71,7 @@ static unsigned char mincore_swap(swp_entry_t entry, bool shmem) */ if (shmem) { si = get_swap_device(entry); - if (!si) + if (IS_ERR_OR_NULL(si)) return 0; } folio = swap_cache_get_folio(entry); diff --git a/mm/shmem.c b/mm/shmem.c index 65572cbf1bd3c..d0a9f52bfed71 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2276,7 +2276,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index, si = get_swap_device(index_entry); order = shmem_confirm_swap(mapping, index, index_entry); - if (unlikely(!si)) { + if (IS_ERR_OR_NULL(si)) { if (order < 0) return -EEXIST; else diff --git a/mm/swap_state.c b/mm/swap_state.c index 4b7a3303c463b..f2e86d6626ecc 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -715,7 +715,7 @@ struct folio *read_swap_cache_async(struct swap_io_ctx *ctx, swp_entry_t entry, struct folio *folio; si = get_swap_device(entry); - if (!si) + if (IS_ERR_OR_NULL(si)) return NULL; mpol = get_vma_policy(vma, addr, 0, &ilx); @@ -951,7 +951,7 @@ static struct folio *swap_vma_readahead(swp_entry_t targ_entry, gfp_t gfp_mask, */ if (swp_type(entry) != swp_type(targ_entry)) { si = get_swap_device(entry); - if (!si) + if (IS_ERR_OR_NULL(si)) continue; } folio = swap_cache_read_folio(&ctx, entry, gfp_mask, mpol, ilx, diff --git a/mm/swapfile.c b/mm/swapfile.c index 9ab11dc24e4f1..29612a0cf7afa 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1504,7 +1504,7 @@ int swap_retry_table_alloc(swp_entry_t entry, gfp_t gfp) unsigned long offset = swp_offset(entry); si = get_swap_device(entry); - if (!si) + if (IS_ERR_OR_NULL(si)) return 0; ci = __swap_offset_to_cluster(si, offset); @@ -1859,7 +1859,9 @@ void folio_put_swap(struct folio *folio, struct page *page) * Check whether swap entry is valid in the swap device. If so, * return pointer to swap_info_struct, and keep the swap entry valid * via preventing the swap device from being swapoff, until - * put_swap_device() is called. Otherwise return NULL. + * put_swap_device() is called. Return NULL for an empty entry or a + * device that is going away, and ERR_PTR(-EINVAL) if the entry itself + * is malformed and can never name a slot on any device. * * Notice that swapoff or swapoff+swapon can still happen before the * percpu_ref_tryget_live() in get_swap_device() or after the @@ -1900,12 +1902,13 @@ struct swap_info_struct *get_swap_device(swp_entry_t entry) return si; bad_nofile: pr_err_ratelimited("%s: %s%08lx\n", __func__, Bad_file, entry.val); + return ERR_PTR(-EINVAL); out: return NULL; put_out: pr_err_ratelimited("%s: %s%08lx\n", __func__, Bad_offset, entry.val); percpu_ref_put(&si->users); - return NULL; + return ERR_PTR(-EINVAL); } /* @@ -2001,7 +2004,7 @@ int swp_swapcount(swp_entry_t entry) int count; si = get_swap_device(entry); - if (!si) + if (IS_ERR_OR_NULL(si)) return 0; ci = swap_cluster_lock(si, swp_offset(entry)); @@ -2127,7 +2130,7 @@ void swap_put_entries_direct(swp_entry_t entry, int nr) struct swap_info_struct *si; si = get_swap_device(entry); - if (WARN_ON_ONCE(!si)) + if (WARN_ON_ONCE(IS_ERR_OR_NULL(si))) return; if (WARN_ON_ONCE(end_offset > si->max)) goto out; diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index 24a4d92ffa3c2..bf7bc7fb1aa0f 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -1700,7 +1700,8 @@ static long move_pages_ptes(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd } si = get_swap_device(entry); - if (unlikely(!si)) { + if (IS_ERR_OR_NULL(si)) { + si = NULL; ret = -EAGAIN; goto out; } diff --git a/mm/zswap.c b/mm/zswap.c index f7c9c89f6449c..bc9b931d6f447 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -997,7 +997,7 @@ static int zswap_writeback_entry(struct zswap_entry *entry, /* try to allocate swap cache folio */ si = get_swap_device(swpentry); - if (!si) + if (IS_ERR_OR_NULL(si)) return -EEXIST; mpol = get_task_policy(current); -- 2.53.0-Meta