From: Breno Leitao <leitao@debian.org>
To: Andrew Morton <akpm@linux-foundation.org>,
Chris Li <chrisl@kernel.org>, Kairui Song <kasong@tencent.com>,
Kemeng Shi <shikemeng@huaweicloud.com>,
Nhat Pham <nphamcs@gmail.com>, Baoquan He <baoquan.he@linux.dev>,
Barry Song <baohua@kernel.org>,
Youngjun Park <youngjun.park@lge.com>,
David Hildenbrand <david@kernel.org>,
Lorenzo Stoakes <ljs@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>,
Mike Rapoport <rppt@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>, Jann Horn <jannh@google.com>,
Pedro Falcato <pfalcato@suse.de>,
Hugh Dickins <hughd@google.com>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
Peter Xu <peterx@redhat.com>,
Johannes Weiner <hannes@cmpxchg.org>,
Yosry Ahmed <yosry@kernel.org>,
Chengming Zhou <chengming.zhou@linux.dev>
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org,
kernel-team@meta.com, Breno Leitao <leitao@debian.org>
Subject: [PATCH 2/3] mm, swap: distinguish a malformed swap entry from a dying device
Date: Mon, 10 Aug 2026 09:26:50 -0700 [thread overview]
Message-ID: <20260810-swap-v1-2-375ef0767206@debian.org> (raw)
In-Reply-To: <20260810-swap-v1-0-375ef0767206@debian.org>
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 <leitao@debian.org>
---
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
next prev parent reply other threads:[~2026-08-10 16:28 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-10 16:26 [PATCH 0/3] mm, swap: don't spin or flood the console on a bad swap entry Breno Leitao
2026-08-10 16:26 ` [PATCH 1/3] mm, swap: ratelimit bad swap entry reports in get_swap_device() Breno Leitao
2026-08-10 16:26 ` Breno Leitao [this message]
2026-08-10 16:26 ` [PATCH 3/3] mm: fail the fault on a malformed swap entry instead of retrying it Breno Leitao
2026-08-10 17:20 ` [PATCH 0/3] mm, swap: don't spin or flood the console on a bad swap entry Andrew Morton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260810-swap-v1-2-375ef0767206@debian.org \
--to=leitao@debian.org \
--cc=akpm@linux-foundation.org \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=baoquan.he@linux.dev \
--cc=chengming.zhou@linux.dev \
--cc=chrisl@kernel.org \
--cc=david@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=hughd@google.com \
--cc=jannh@google.com \
--cc=kasong@tencent.com \
--cc=kernel-team@meta.com \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@suse.com \
--cc=nphamcs@gmail.com \
--cc=peterx@redhat.com \
--cc=pfalcato@suse.de \
--cc=rppt@kernel.org \
--cc=shikemeng@huaweicloud.com \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=yosry@kernel.org \
--cc=youngjun.park@lge.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox