[PATCH v4 12/15] mm/shmem: preserve allocation errors when swapping in large entries

From: David Hildenbrand (Arm)

Date: Thu Oct 29 2026 - 06:46:23 EST


shmem_swapin_folio() adjusts swap to the requested slot within a large
swap entry before allocating a folio. If allocation or charging fails,
the error path compares this adjusted value with the original entry
still stored in the XArray in shmem_confirm_swap().

Unless the index is at the start of the entry, this turns -ENOMEM into
-EEXIST even though nothing changed.

The caller retries -EEXIST, so persistent allocation failures can leave
the task spinning instead of returning the error.

Restore swap to index_entry on allocation failure so the existing error
path checks the original entry. This preserves the allocation error if
the entry is unchanged and still retries if it changed concurrently.

Fixes: 91ab656ece13 ("mm/shmem, swap: tidy up swap entry splitting")
Cc: stable@xxxxxxxxxxxxxxx
Reported-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
Acked-by: Kiryl Shutsemau (Meta) <kas@xxxxxxxxxx>
Reviewed-by: Baolin Wang <baolin.wang@xxxxxxxxxxxxxxxxx>
Tested-by: Gregory Price (Meta) <gourry@xxxxxxxxxx>
Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
---
mm/shmem.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/mm/shmem.c b/mm/shmem.c
index e1b7cf4b5280..02de6326ef3b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2552,6 +2552,8 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
else
error = -ENOMEM;
folio = NULL;
+ /* Make sure to validate the original value. */
+ swap = index_entry;
goto failed;
}
if (fault_type) {

--
2.43.0